最近在读刘增辉老师所著的《MyBatis 从入门到精通》一书, 很有收获, 于是将自己学习的过程以博客形式输出, 如有错误, 欢迎指正, 如帮助到你, 不胜荣幸!
本篇博客主要讲解 MyBatis 中如何使用 collection 标签实现查询结果一对多映射.
1. 使用 collection 标签
需求: 根据用户 id 查询用户信息的同时获取用户拥有的角色, 一个用户可以拥有 1 个或多个角色.
一般情况下, 不建议直接修改数据库表对应的实体类.
所以这里我们延用之前博客中新建的类 SysUserExtend, 并添加如下代码, 如下所示:
- /**
- * 用户的角色集合
- */
- private List<SysRole> sysRoleList;
- public List<SysRole> getSysRoleList() {
- return sysRoleList;
- }
- public void setSysRoleList(List<SysRole> sysRoleList) {
- this.sysRoleList = sysRoleList;
- }
然后, 我们在接口 SysUserMapper 中添加如下方法:
- /**
- * 获取所有的用户以及对应的所有角色
- *
- * @return
- */
- List<SysUserExtend> selectAllUserAndRoles();
接着, 在对应的 SysUserMapper.xml 中添加如下代码:
- <resultMap id="userRoleListMap" type="com.zwwhnly.mybatisaction.model.SysUserExtend" extends="sysUserMap">
- <collection property="sysRoleList" columnPrefix="role_"
- ofType="com.zwwhnly.mybatisaction.model.SysRole">
- <id property="id" column="id"/>
- <result property="roleName" column="role_name"/>
- <result property="enabled" column="enabled"/>
- <result property="createBy" column="create_by"/>
- <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
- </collection>
- </resultMap>
因为我们在前面的博客中已经建过角色表的 roleMap:
- <resultMap id="roleMap" type="com.zwwhnly.mybatisaction.model.SysRole">
- <id property="id" column="id"/>
- <result property="roleName" column="role_name"/>
- <result property="enabled" column="enabled"/>
- <result property="createBy" column="create_by"/>
- <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
- </resultMap>
所以上面的 collection 标签可以简化为:
- <collection property="sysRoleList" columnPrefix="role_"
- resultMap="com.zwwhnly.mybatisaction.mapper.SysRoleMapper.roleMap">
- </collection>
新建接口对应的查询代码, 使用上面新建的 userRoleListMap, 如下所示:
- <select id="selectAllUserAndRoles" resultMap="userRoleListMap">
- SELECT
- u.id,
- u.user_name,
- u.user_password,
- u.user_email,
- u.create_time,
- r.id role_id,
- r.role_name role_role_name,
- r.enabled role_enabled,
- r.create_by role_create_by,
- r.create_time role_create_time
- FROM sys_user u
- INNER JOIN sys_user_role ur ON u.id = ur.user_id
- INNER JOIN sys_role r ON ur.role_id = r.id
- </select>
最后, 在 SysUserMapperTest 测试类中添加如下测试方法:
- @Test
- public void testSelectAllUserAndRoles() {
- SqlSession sqlSession = getSqlSession();
- try {
- SysUserMapper sysUserMapper = sqlSession.getMapper(SysUserMapper.class);
- List<SysUserExtend> sysUserList = sysUserMapper.selectAllUserAndRoles();
- System.out.println("用户数:" + sysUserList.size());
- for (SysUserExtend sysUser : sysUserList) {
- System.out.println("用户名:" + sysUser.getUserName());
- for (SysRole sysRole : sysUser.getSysRoleList()) {
- System.out.println("角色名:" + sysRole.getRoleName());
- }
- }
- } finally {
- sqlSession.close();
- }
- }
运行测试代码, 测试通过, 输出日志如下:
- DEBUG [main] - ==> Preparing: SELECT u.id, u.user_name, u.user_password, u.user_email, u.create_time, r.id role_id, r.role_name role_role_name, r.enabled role_enabled, r.create_by role_create_by, r.create_time role_create_time FROM sys_user u INNER JOIN sys_user_role ur ON u.id = ur.user_id INNER JOIN sys_role r ON ur.role_id = r.id
- DEBUG [main] - ==> Parameters:
- TRACE [main] - <== Columns: id, user_name, user_password, user_email, create_time, role_id, role_role_name, role_enabled, role_create_by, role_create_time
TRACE [main] - <== Row: 1, admin, 123456, admin@mybatis.tk, 2019-06-27 18:21:07.0, 1, 管理员, 1, 1, 2019-06-27 18:21:12.0
TRACE [main] - <== Row: 1, admin, 123456, admin@mybatis.tk, 2019-06-27 18:21:07.0, 2, 普通用户, 1, 1, 2019-06-27 18:21:12.0
TRACE [main] - <== Row: 1001, test, 123456, test@mybatis.tk, 2019-06-27 18:21:07.0, 2, 普通用户, 1, 1, 2019-06-27 18:21:12.0
DEBUG [main] - <== Total: 3
用户数: 2
用户名: admin
角色名: 管理员
角色名: 普通用户
用户名: test
角色名: 普通用户
2. MyBatis 合并规则
观察上面的日志, 我们的 Sql 语句查询到了 3 条数据, 在数据库查询的话, 也是返回如下的数据:
但经过 MyBatis 配置的映射到, 最后合并为了 2 个用户, 其中第 1 个用户包含了 2 个角色, 第 2 个用户包含了 1 个角色, 那么 MyBatis 是根据什么规则合并的呢?
MyBatis 在处理结果的时候, 会判断结果是否相同, 如果是相同的结果, 则只会保留第一个结果, 所以关键点就是 MyBatis 如何判断结果是否相同.
- <resultMap id="sysUserMap" type="com.zwwhnly.mybatisaction.model.SysUser">
- <id property="userPassword" column="user_password"/>
- <result property="id" column="id"/>
- <result property="userName" column="user_name"/>
- <result property="userEmail" column="user_email"/>
- <result property="userInfo" column="user_info"/>
- <result property="headImg" column="head_img" jdbcType="BLOB"/>
- <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
- </resultMap>
来源: https://www.cnblogs.com/zwwhnly/p/11194028.html