Mybatis框架的使用之四(resultMap的使用)
绝大多数情况下,一条完整的信息至少分别来自两张或以上的表,连表查询非常常见,这种情况下可以使用resultMap属性
1、使用resultMap实现简单结果映射:
user表:
role表:
user表中的userRole是外键,对应role表中的id
需求:通过userName和userRole,查询到符合条件的用户和其RoleName
在这里,用户信息来自user表,roleName来自role表。我们采用封装对象的传参的方式进行查询。首先可以修改pojo的User类,添加一个userRoleName的String属性和相应的setter、getter方法
然后在mapper文件中新建一个select标签:
<select id="getUserList" resultMap="userList" parameterType="User"> select u.*,r.roleName from smbms_user AS u,smbms_role AS r where u.userName like CONCAT('%',#{userName},'%') AND u.userRole = #{userRole} AND u.userRole = r.id </select>
这里没有使用resultType标签了,而是换成了resultMap,它的值由我们自定义。
然后,在刚刚编写完成select标签外,创建一个resultMap标签:
<!--id与使用resultMap属性的标签值一致,type是返回类型--> <resultMap id="userList" type="User"> <!--column是表的列名 property是查出来的字段值要赋给的实体对象的属性名称--> <!--意味着我们采用自定义的方式进行映射--> <result property="id" column="id"></result> <result property="userCode" column="userCode"></result> <result property="userName" column="userName"></result> <!--在这里把role表的roleName列的值赋给了User类的userRoleName属性--> <result property="userRoleName" column="roleName"></result> </resultMap>
接口方法没有什么新变化:
List<User> getUserList(User user);
测试类:
public void getUserList() { SqlSession sqlSession = null; List<User> list; User u = new User(); u.setUserName("赵"); u.setUserRole(2); try { sqlSession = MyBatisUtils.getSQLSession(); list = sqlSession.getMapper(UserMapper.class).getUserList(u); for (User user : list) logger.debug("UserCode:" + user. 24000 getUserCode() + "\tUserRoleName:" + user.getUserRoleName() + "\tUserName:" + user.getUserName() + "\tUserAddress:" + user.getAddress()); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } finally { MyBatisUtils.closeSqlSession(sqlSession); } }
可以得到的查询结果是:
UserCode:zhaomin UserRoleName:经理 UserName:赵敏 UserAddress:北京市昌平区天通苑3区12号楼
引申说明:这里是涉及到一个叫做自动映射级别(autoMappingBehavior)的属性,设置的位置是在mybatis-config.xml核心配置文件中标签中的一个,一共三个value,分别是"NONE" “FULL” 和 “PARTIAL”
FULL:自动匹配所有属性
NONE:禁止自动匹配(只能依靠自定义resultMap,没有定义的都会是null)
PARTIAL:默认,自动匹配所有属性,内部嵌套除外
<settings> <setting name="logImpl" value="LOG4J" /> <setting name="autoMappingBehavior" value="FULL" /> </settings>
resultType和resultMap的区别:
resultType直接表示了返回类型,可以是基本数据类型,也可以是复杂数据类型。
resultMap,是对外部resultMap的引用,用于数据库字段信息与对象属性不一致的情况,可以完成较复杂的联合查询。
二者本质上都是Map数据结构,不要同时使用。
2、使用resultMap实现高级结果映射
resultMap属性
id:resultMap的唯一标识
type:Java实体类
resultMap子元素:
id:一般对应数据库中该行的主键id,设置此项可提高mybatis性能
result:映射到JavaBean的某个“简单类型”属性
association:映射到JavaBean的某个“复杂类型”属性,比如JavaBean类
collection:映射到JavaBean的某个“复杂类型”属性,比如集合
association:
复杂的类型关联,一对一
内部嵌套:映射一个嵌套JavaBean属性(一个JavaBean作为另一个JavaBean的属性)
属性:
property:映射数据库列的实体对象的属性
javaType:完整Java类名或者别名
resultMap:引用外部resultMap
子元素:
- id
- result:
Property:映射数据库列的实体对象的属性
column:数据库列名或者别名
应用情景:多表查询多个字段,如果每一个字段都要"复制"到同一个JavaBean实体类中,非常繁琐。这种情况可以使用JavaBean的嵌套。
例如一个user类,含有一个role类的属性。这样相当于把role类的所有属性都封装并放入了user类。
先添加一个接口方法:通过角色id获得相应的用户列表
List<User> getUserListByRoleId(@Param("userRole") Integer roleId);
mapper文件:
<resultMap type="User" id="userRoleResult"> <id property="id" column="id"/> <result property="userCode" column="userCode"/> <result property="userName" column="userName"/> <result property="userRole" column="userRole"/> <association property="role" javaType="Role" resultMap="roleResult"/> </resultMap> <resultMap type="Role" id="roleResult"> <id property="id" column="r_id"/> <result property="roleCode" column="roleCode"/> <result property="roleName" column="roleName"/> </resultMap> <select id="getUserListByRoleId" parameterType="Integer" resultMap="userRoleResult"> select u.*,r.id as r_id,r.roleCode,r.roleName from smbms_user AS u,smbms_role AS r where u.userRole = #{userRole} and u.userRole = r.id </select>
这里相对复杂,解释如下:
首先创建了select语句,因为是连表查询,因此通过resultMap ="userRoleResult"进行第一次映射。
在userRoleResult这个resultMap中,返回的对象其实依旧是User,
然后 < id property=“id” column=“id”/ >中的第一个id就是User类中的id属性名,就叫id。column中的id是对应的列名或者别名,因为在查询语句中没有起别名,所以就是user表的id列的列名:id。
然后是常规的result自定义映射,如果在mybatis-config.xml配置文件中将autoMappingBehavior的value设置为"FULL"的话,所有的result映射都可以不做,因为会进行全局的同名自动映射。
然后需要添加
< association property=“role” javaType=“Role” resultMap=“roleResult”/ >这个标签。因为在User这个类中嵌套了Role,所以需要再次的resultMap,property就是在JavaBean中要映射的JavaBean的属性名,在这里就是User类中的Role role;属性名是role,javaType就是要映射的类的完整限定名,因为在配置文件中已经配置了
<typeAliases> <package name="cn.smbms.pojo" /> </typeAliases>,所以这里直接写Role就可以。然后要对Role再做映射配置,所以再次resultMap到roleResult
在id为roleResult的resultMap中,返回的类型type自然是Role,然后这里面的子节点 < id property=“id” column=“r_id”/ >property的id就是Role这个类中id的属性名,就是id,而column则是表中的列名,因为在sql语句中起了别名,因此是r_id
下面依旧是常规的result映射…
全部完成后的测试方法:
public void getUserListByRoleIdTest() { SqlSession sqlSession = null; List<User> userList = new ArrayList<>(); Integer roleId = 3; try { sqlSession = MyBatisUtils.getSQLSession(); userList = sqlSession.getMapper(UserMapper.class).getUserListByRoleId(roleId); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } finally { MyBatisUtils.closeSqlSession(sqlSession); } logger.debug("getUserListByRoleIdTest userList.size : " + userList.size()); for (User user : userList) { logger.debug("userList =====> userName: " + user.getUserName() + ", userPassword: " + user.getUserPassword() + ", Role: " + user.getRole().getId() + " --- " + user.getRole().getRoleCode() + " --- " + user.getRole().getRoleName()); } }
运行结果没有问题:
以上就是association在处理一对一情况下的使用,而在处理一对多的时候,就需要使用另一个属性:collection
collection:
复杂类型集合,一对多
内部嵌套:映射一个嵌套结果集到一个列表
属性:
property:映射数据库列的实体对象的属性
ofType:完整Java类名或者别名(集合所包括的类型)
resultMap:引用外部resultMap
子元素:
id
result:
property:映射数据库列的实体对象的属性
column:数据库列名或者别名
模拟需求:获取指定id的用户信息和地址列表(同一用户有多个不同地址)
这里需要引入一张address表,同时创建Address的pojo类
完成后,需要在User类中添加一个List集合,泛型为Address,并生成setter和getter方法
private List<Address> addressList;//用户地址列表 public List<Address> getAddressList() { return addressList; } public void setAddressList(List<Address> addressList) { this.addressList = addressList; }
然后在接口类中增加方法:
List<User> getAddressListByUserId(@Param("id") Integer userId);
mapper文件:
<resultMap type="User" id="userAddressResult"> <id property="id" column="id"/> <result property="userCode" column="userCode"/> <result property="userName" column="userName"/> <collection property="addressList" ofType="Address" resultMap="addressResult"/> </resultMap> <resultMap type="Address" id="addressResult"> <id property="id" column="a_id"/> <result property="postCode" column="postCode"/> <result property="tel" column="tel"/> <result property="contact" column="contact"/> <result property="addressDesc" column="addressDesc"/> </resultMap> <select id="getAddressListByUserId" parameterType="Integer" resultMap="userAddressResult"> select u.*,a.id as a_id,a.contact,a.addressDesc,a.postCode,a.tel,a.userId from smbms_user u LEFT JOIN smbms_address a ON u.id = a.userId where u.id=#{id} </select>
这里的用法跟association基本相似,不同的是< collection property=“addressList” ofType=“Address” resultMap=“addressResult”/ >
这里的property指的是在JavaBean中所映射的数据库类的实体对象的属性名,这个属性是 private List< Address> addressList; 属性名就是addressList。
ofType是完整的类名或别名,也就是集合所包含的类型。依旧可以直接使用别名Address。
id、result的配置与association中的一致
测试方法:
public void getAddressListByUserIdTest() { SqlSession sqlSession = null; List<User> userList = new ArrayList<>(); Integer userId = 1; try { sqlSession = MyBatisUtils.getSQLSession(); userList = sqlSession.getMapper(UserMapper.class).getAddressListByUserId(userId); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } finally { MyBatisUtils.closeSqlSession(sqlSession); } for (User user : userList) { logger.debug("userCode:" + user.getUserCode() + "\tuserName:" + user.getUserName()); //遍历到address的值的时候,因为它是个集合,所以再嵌套一个循环 for (Address address : user.getAddressList()) { logger.debug("address---->" + address.getId() + "\tcontact:" + address.getContact() + "\taddressDesc:" + address.getAddressDesc() ); } } }
测试的结果没有问题:
Mybatis框架的使用之五传送门:
https://www.geek-share.com/detail/2756109810.html
- MyBatis框架核心之(四)Mapper文件使用resultMap及多表查询
- MyBatis框架核心之(五)注解使用resultMap及多表查询
- 框架学习系列 mybatis 第十八篇 高级结果一对一结果映射之resultMap的使用
- 【Mybatis】表关联和resultMap的使用
- Mybatis自定义ResultMap使用总结
- mybatis 使用resultMap实现数据库的操作
- MyBatis使用 resultMap的association 标签实现懒加载
- mybatis中resultMap 标签的使用教程
- MyBatis的ResultMap使用方法,对象关联写法
- Mybatis的ResultMap的使用
- mybatis 的 resultMap 的使用
- 知了堂学习笔记--mybatis学习_resultMap的使用
- 使用mybatis的resultType="Map"可省去new返回值对象
- Mybatis框架提供的resultMap返回值别名
- Mybatis的ResultMap的使用
- 【Mybatis框架】输出映射-resultType与resultMap
- Mybatis学习记录(四)----resultMap的使用
- Mybatis---查询使用resultType和resultMap的区别
- mybatis 使用resultMap实现关联数据的查询(association 和collection )