mybatis从入门到精通(三) 结果映射
mybatis从入门到精通(三) 结果映射
一丶什么是结果映射
结果映射是用于将数据库表字段和实体类中的属性名映射起来, 即究竟是哪个字段名与属性名对应. 映射之后, 即可通过mybatis将从数据库查询的结果转换成对应的实体类对象类型, 除去了人工转换的麻烦.
二丶自动映射
所谓的自动映射, 即是默认java实体类的属性名是驼峰式, 而数据库表字段名是以下划线分隔, 如 属性名userName 与 表字段user_name相对应, 如果是这种简单通用的规则, 即可通过配置mybatis, 使得mybatis自动映射.
1) 在mybatis-config.xml中配置开启下划线和驼峰式的自动映射
settings> <!-- 是否开启下划线和驼峰式的自动转换, http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html#Auto-mapping --> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>
2) 在userReulstMapper.xml中配置对应的<ResultMap>, 只需配置id即可, 用于指定唯一标识, 其他映射由mybatis自动处理
<!-- 使用下划线和驼峰式的自动映射(autoMapping)转换, http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html#Auto-mapping, 需要在mybatis-config.xml配置文件中配置mapUnderscoreToCamelCase属性为true, 可在resultMap中设置autoMapping来控制是否开启自动映射, 默认为true --> <resultMap id="UserAutoResultMap" type="com.ttx.example.pojo.UserResult" autoMapping="true"> <id column="user_id"/> <!-- 标识主键--> </resultMap>
3) 写入mapper查询方法
UserResultMapper.java
List<UserResult> selectUserByUserNameLike(@Param("userName") String userName);
UserResultMapper.xml
<select id="selectUserByUserNameLike" resultMap="UserAutoResultMap"> select * from user where user_name like #{userName} </select>
4) ResultMapTests.java 测试类方法
@Test public void autoMappingTest(){ // 测试结果集下划线和驼峰式的自动映射转换 List<UserResult> userResults=userResultMapper.selectUserByUserNameLike("t%"); Assert.assertTrue(userResults.size()>1); }
二丶普通的单表结果映射
如下方的结果映射配置, type标明该配置会映射转换成对应的实体类型, 其中子元素<id/>用于标明该字段为唯一标识, 用于区分多条数据, <result/>则是普通的字段映射.
column属性用于指明表字段名, property用于指明对应实体类的属性名
<resultMap id="UserMap" type="com.ttx.example.entity.User"> <id column="user_id" property="userId"/> <result column="user_name" property="userName"/> <result column="age" property="age"/> <result column="country" property="country"/> </resultMap>
更多配置细节可以查看官方文档
三丶关联结果映射
一般的应用, 肯定不仅仅只是单表查询这么简单, 还会存在多表关联查询. 此时,查询的结果会很是复杂, 因此有了 关联<association/> 和 集合<collection/> 映射.
关联<association/> 和 集合<collection/> 作用类似, <collection/> 主要是多了ofType属性, 用于指明List<ofType>中的泛型类型, 但一般无须配置, mybatis会自动处理.
首先, 我们来看两张单表对应的实体类
public class UserResult { private Integer userId; private String userName; private Integer age; private String country; public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } }
public class Email { private Integer emailId; private Integer userId; private String emailAddress; private String password; public Integer getEmailId() { return emailId; } public void setEmailId(Integer emailId) { this.emailId = emailId; } public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public String getEmailAddress() { return emailAddress; } public void setEmailAddress(String emailAddress) { this.emailAddress = emailAddress; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
再看, 关联的pojo类
public class UserResultEmail { private Integer userId; //需要使用userId标识 private UserResult userResult; private List<Email> emailList; // 关联 或者 集合 public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public UserResult getUserResult() { return userResult; } public void setUserResult(UserResult userResult) { this.userResult = userResult; } public List<Email> getEmailList() { return emailList; } public void setEmailList(List<Email> emailList) { this.emailList = emailList; } }
2) 关联的映射配置如下:
<resultMap id="UserResultMap" type="com.ttx.example.pojo.UserResult"> <constructor></constructor> <!-- 用于引用构造参数, 可以省略掉 --> <id column="user_id" property="userId"/> <!-- id 元素表示的结果将是对象的标识属性 --> <result column="user_name" property="userName"/> <result column="age" property="age"/> <result column="country" property="country"/> </resultMap> <resultMap id="EmailMap" type="com.ttx.example.pojo.Email"> <id column="email_id" property="emailId"/> <!-- id 元素表示的结果将是对象的标识属性 --> <result column="user_id" property="userId"/> <!-- 关联userResult的user_id属性--> <result column="email_address" property="emailAddress"/> <result column="password" property="password"/> </resultMap>
<resultMap id="UserResultEmailMap" type="com.ttx.example.pojo.UserResultEmail"> <id column="user_id" property="userId"/> <!-- 由于是关联查询,会返回多个结果集, 需要指定唯一标识,去掉重复的值 --> <association property="userResult" resultMap="UserResultMap"/> <collection ofType="com.ttx.example.pojo.Email" column="email_id" property="emailList" resultMap="EmailMap"/> <!-- association,collection 关联查询, 用法差不多,区别在于ofType类型, 可以指定集合的具体类型 --> </resultMap>
3) mapper对应的方法
UserResultMapper.java
UserResultEmail selectUserAndEmailByUserId(@Param("userId") int userId);
UserResultMapper.xml
<select id="selectUserAndEmailByUserId" resultMap="UserResultEmailMap" > select * from user u,email e where u.user_id=#{userId} and u.user_id=e.user_id </select>
4) 测试类方法
@Test public void associationTest(){ UserResultEmail userResultEmail=userResultMapper.selectUserAndEmailByUserId(1); Assert.assertTrue(userResultEmail!=null); System.out.println("userName: "+userResultEmail.getUserResult().getUserName()); System.out.println("emailSize: "+userResultEmail.getUserResult().getUserName()); }
学习资料: