前言
我们在实际开发的时候,有没有遇到数据库字段和我们实体类中字段不一样的时候。这个时候 Mybatis 有没有提供解决方案呢?作为一个程序框架肯定是考虑到了这点。举个例子我们数据库表像下面这样。直接给出 SQL,在数据库中执行就行了,还是放在我们的 mybatis
数据库中:
1 | CREATE TABLE users_test ( |
2 | `id` int(20) UNSIGNED NOT NULL AUTO_INCREMENT, |
3 | `name` VARCHAR(64) NOT NULL, |
4 | `pwd` VARCHAR(64) NOT NULL, |
5 | PRIMARY KEY(`id`) |
6 | ) ENGINE=INNODB DEFAULT CHARSET=utf8mb4; |
7 | |
8 | INSERT INTO `users_test` (`name`, `pwd`) VALUES ('鱼不浪', '666666'), ('鲁班', '666666'), ('西施', '666666'), ('麦特凯', '666666'); |
而我们的实体类是 com.yubulang.pojo.UserTest
,里面的 password
与 数据库表的 pwd
现在是没有办法对应匹配的。我们需要让实体类与他绑定。
1 | package com.yubulang.pojo; |
2 | |
3 | public class UserTest { |
4 | private int id; |
5 | private String name; |
6 | private String password; |
7 | |
8 | ... |
9 | } |
为了复习之前的知识点,我们新建一个项目: mybatis-demo
,一路下一步。哈哈哈
连接数据库配置
有了前面章节配置的学习,我们知道要在项目 resources
创建对应 db.properties
, mybatis-config.xml
配置。
db.properties 如下:
1 | driver=com.mysql.jdbc.Driver |
2 | url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Hongkong |
3 | username=root |
4 | password= |
创建完对应的属性,我们需要创建对应的 mybatis-config.xml
配置,${字段名}
就是我们 db.properties
对应的字段信息:
1 |
|
2 |
|
3 |
|
4 |
|
5 | <configuration> |
6 | <!-- 引入数据库相关属性 --> |
7 | <properties resource="db.properties"/> |
8 | |
9 | <environments default="development"> |
10 | <environment id="development"> |
11 | <transactionManager type="JDBC"/> |
12 | <dataSource type="POOLED"> |
13 | <property name="driver" value="${driver}"/> |
14 | <property name="url" value="${url}"/> |
15 | <property name="username" value="${username}"/> |
16 | <property name="password" value="${password}"/> |
17 | </dataSource> |
18 | </environment> |
19 | </environments> |
20 | </configuration> |
有了这些基础配置,为了方便我们去使用 Mybatis,我们还需要写一个对应的 com.yubulang.utils.MybatisUtils
工具类:
1 | package com.yubulang.utils; |
2 | |
3 | import org.apache.ibatis.io.Resources; |
4 | import org.apache.ibatis.session.SqlSession; |
5 | import org.apache.ibatis.session.SqlSessionFactory; |
6 | import org.apache.ibatis.session.SqlSessionFactoryBuilder; |
7 | |
8 | import java.io.IOException; |
9 | import java.io.InputStream; |
10 | |
11 | public class MybatisUtils { |
12 | private static SqlSessionFactory sqlSessionFactory; |
13 | |
14 | static { |
15 | String resource = "mybatis-config.xml"; |
16 | |
17 | try { |
18 | InputStream in = Resources.getResourceAsStream(resource); |
19 | sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); |
20 | } catch (IOException e) { |
21 | e.printStackTrace(); |
22 | } |
23 | } |
24 | |
25 | public static SqlSession getSqlSession() { |
26 | return sqlSessionFactory.openSession(); |
27 | } |
28 | } |
在这里我们已经可以连接我们的数据库了,在连接完数据库,我们需要创建我们的实体类 com.yubulang.pojo.UserTest
:
1 | package com.yubulang.pojo; |
2 | |
3 | public class UserTest { |
4 | private int id; |
5 | private String name; |
6 | private String password; |
7 | |
8 | public UserTest() { |
9 | } |
10 | |
11 | public UserTest(int id, String name, String password) { |
12 | this.id = id; |
13 | this.name = name; |
14 | this.password = password; |
15 | } |
16 | |
17 | public int getId() { |
18 | return id; |
19 | } |
20 | |
21 | public void setId(int id) { |
22 | this.id = id; |
23 | } |
24 | |
25 | public String getName() { |
26 | return name; |
27 | } |
28 | |
29 | public void setName(String name) { |
30 | this.name = name; |
31 | } |
32 | |
33 | public String getPassword() { |
34 | return password; |
35 | } |
36 | |
37 | public void setPassword(String password) { |
38 | this.password = password; |
39 | } |
40 | |
41 | |
42 | public String toString() { |
43 | return "User{" + |
44 | "id=" + id + |
45 | ", name='" + name + '\'' + |
46 | ", password='" + password + '\'' + |
47 | '}'; |
48 | } |
49 | } |
这一步完成后,我们已经有了实体类,这个时候就是创建对应的 Mapper 了,我们创建 com.yubulang.dao.UserTestMapper
这个实现接口类:
1 | package com.yubulang.dao; |
2 | |
3 | import com.yubulang.pojo.UserTest; |
4 | |
5 | import java.util.List; |
6 | |
7 | public interface UserTestMapper { |
8 | List<UserTest> getUserTestList(); |
9 | } |
有了对应的实现接口,我们也要创建对应的 com.yubulang.dao.UserTestMapper.xml
让我们进行对其进行配置:
1 |
|
2 |
|
3 |
|
4 |
|
5 | |
6 | <!-- 注意这里的 namespace 是我们要隐射的实现接口类 --> |
7 | <mapper namespace="com.yubulang.dao.UserTestMapper"> |
8 | <!-- resultType 返回值类型,这里我们简单的,一会儿去 mybatis-config.xml 配置 --> |
9 | <select id="getUserTestList" resultType="UserTest"> |
10 | select * from users_test; |
11 | </select> |
12 | </mapper> |
有了这个隐射文件,我们需要将其对应的路径引入到我们的 mybatis-config.xml
中去,当然还要配置对应的实体类别名:
1 |
|
2 |
|
3 |
|
4 |
|
5 | <configuration> |
6 | <properties resource="db.properties"/> |
7 | |
8 | <typeAliases> |
9 | <typeAlias type="com.yubulang.pojo.UserTest" alias="UserTest"/> |
10 | </typeAliases> |
11 | |
12 | <environments default="development"> |
13 | <environment id="development"> |
14 | <transactionManager type="JDBC"/> |
15 | <dataSource type="POOLED"> |
16 | <property name="driver" value="${driver}"/> |
17 | <property name="url" value="${url}"/> |
18 | <property name="username" value="${username}"/> |
19 | <property name="password" value="${password}"/> |
20 | </dataSource> |
21 | </environment> |
22 | </environments> |
23 | |
24 | <mappers> |
25 | <mapper resource="com/yubulang/dao/UserTestMapper.xml"/> |
26 | </mappers> |
27 | </configuration> |
实现代码这里已经是 Ok 的了。我们需要在 test/java
目录下创建一个 com.yubulang.dao.UserTestMapperTest
的测试文件来测试我们的代码:
1 | package com.yubulang.dao; |
2 | |
3 | import com.yubulang.pojo.UserTest; |
4 | import com.yubulang.utils.MybatisUtils; |
5 | import org.apache.ibatis.session.SqlSession; |
6 | import org.junit.Test; |
7 | |
8 | import java.util.List; |
9 | |
10 | public class UserTestMapperTest { |
11 | |
12 | public void testGetUserTestList() { |
13 | SqlSession sqlSession = MybatisUtils.getSqlSession(); |
14 | |
15 | UserTestMapper mapper = sqlSession.getMapper(UserTestMapper.class); |
16 | |
17 | List<UserTest> userTestList = mapper.getUserTestList(); |
18 | for (UserTest userTest : userTestList) { |
19 | System.out.println(userTest); |
20 | } |
21 | |
22 | sqlSession.close(); |
23 | } |
24 | } |
运行测试,我们可以发现运行结果 password
是 null
而 name
正常输出。
1 | User{id=1, name='鱼不浪', password='null'} |
2 | User{id=2, name='鲁班', password='null'} |
3 | User{id=3, name='西施', password='null'} |
4 | User{id=4, name='麦特凯', password='null'} |
到这里,我们才是要开始解决我们的问题。其实解决这个问题的方法也简单,我们可以直接修改 com.yubulang.dao.UserTestMapper.xml
的 select sql 语句,改成下面这样:
1 | select id, name, pwd as password from users_test; |
这样一样能达成我们的效果,但是这显然有点笨。我们来看看科学的方法。
resultMap 结果集映射
从字面表达来说,结果集映射故名思意就是把结果集中的字段与我们的实体类字段隐射关联一下。我们还是对 com.yubulang.dao.UserTestMapper.xml
进行修改。
1 |
|
2 |
|
3 |
|
4 |
|
5 | |
6 | <mapper namespace="com.yubulang.dao.UserTestMapper"> |
7 | <!-- 结果集隐射 --> |
8 | <resultMap id="UserTestMap" type="UserTest"> |
9 | <!-- 让对应的列名,对应我们的实体类属性 --> |
10 | <result column="id" property="id"/> |
11 | <result column="name" property="name"/> |
12 | <result column="pwd" property="password"/> |
13 | </resultMap> |
14 | |
15 | <!-- 原来的返回类型resultType 替换成为 resultMap --> |
16 | <select id="getUserTestList" resultMap="UserTestMap"> |
17 | select * from users_test; |
18 | </select> |
19 | </mapper> |
- resultMap 元素是 MyBatis 中最重要最强大的元素
- ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了
- ResultMap 的优秀之处——你完全可以不用显式地配置它们,可以把有需要隐射的字段来隐射
所以,我们这里只需要保留下不一样的需要隐射的字段就好了:
1 |
|
2 |
|
3 |
|
4 |
|
5 | |
6 | <mapper namespace="com.yubulang.dao.UserTestMapper"> |
7 | <!-- 结果集隐射 --> |
8 | <resultMap id="UserTestMap" type="UserTest"> |
9 | <!-- 让对应的列名,对应我们的实体类属性 --> |
10 | <!-- <result column="id" property="id"/> --> |
11 | <!-- <result column="name" property="name"/> --> |
12 | <result column="pwd" property="password"/> |
13 | </resultMap> |
14 | |
15 | <!-- 原来的返回类型resultType 替换成为 resultMap --> |
16 | <select id="getUserTestList" resultMap="UserTestMap"> |
17 | select * from users_test; |
18 | </select> |
19 | </mapper> |
总结
这里只是开胃菜,我们在项目中会有很多更加复杂的形式,一点点深入我们会接触到。就如文档中说的那样,世界如果总是这么简单就好了。不过还是劝解大家醒醒哈哈哈