最近在读刘增辉老师所著的《MyBatis从入门到精通》一书,颇有收获,因而将本身学习的过程以博客形式输出,若有错误,欢迎指正,如帮助到你,不胜荣幸!java
上篇博客中,咱们示例的2个查询都是单表查询,但实际的业务场景确定是须要多表查询的,好比如今有个需求:git
查询某个用户拥有的全部角色。这个需求要涉及到sys_user,sys_user_role,sys_role三张表,如何实现呢?github
首先,在SysUserMapper接口中定义以下方法。sql
/** * 根据用户id获取角色信息 * * @param userId * @return */ List<SysRole> selectRolesByUserId(Long userId);
而后打开对应的SysUserMapper.xml文件,添加以下select语句:微信
<select id="selectRolesByUserId" resultType="com.zwwhnly.mybatisaction.model.SysRole"> SELECT r.id, r.role_name roleName, r.enabled, r.create_by createBy, r.create_time createTime 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 WHERE u.id = #{userId} </select>
细心的读者可能会发现,咱们虽然使用到了多表查询,可是resultType设置的仍然是单表,即只包含角色表的信息。mybatis
若是我但愿这个查询语句同时返回SysUser表的user_name字段呢,该如何设置resultType?app
方法1:直接在SysRole实体类中添加userName字段。工具
private String userName; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; }
此时resultType不用修改。学习
方法2:新建扩展类,在扩展类中添加userName字段。测试
package com.zwwhnly.mybatisaction.model; public class SysRoleExtend extends SysRole { private String userName; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } }
此时须要将resultType修改成:com.zwwhnly.mybatisaction.model.SysRoleExtend。
这种方式比较适合须要少许额外字段的场景。若是须要其余表的大量字段,可使用方式3或者方式4,我的推荐使用方式4。
方法3:在SysRole实体类中添加SysUser类型的字段。
private SysUser sysUser; public SysUser getSysUser() { return sysUser; } public void setSysUser(SysUser sysUser) { this.sysUser = sysUser; }
此时resultType不用修改。
方法4(推荐使用):新建扩展类,在扩展类中添加SysUser类型的字段。
书中推荐的是方式3,方式4是我我的认为更好的方式,由于实体类通常由工具自动生成,增长了字段后,后续容易忘记致使被覆盖掉。
package com.zwwhnly.mybatisaction.model; public class SysRoleExtend extends SysRole { private SysUser sysUser; public SysUser getSysUser() { return sysUser; } public void setSysUser(SysUser sysUser) { this.sysUser = sysUser; } }
此时须要将resultType修改成:com.zwwhnly.mybatisaction.model.SysRoleExtend。
此时xml中的查询语句以下。
<select id="selectRolesByUserId" resultType="com.zwwhnly.mybatisaction.model.SysRoleExtend"> SELECT r.id, r.role_name roleName, r.enabled, r.create_by createBy, r.create_time createTime, u.user_name "sysUser.userName", u.user_email "sysUser.userEmail" 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 WHERE u.id = #{userId} </select>
在SysUserMapperTest中添加测试代码以下。
@Test public void testSelectRolesByUserId() { SqlSession sqlSession = getSqlSession(); try { SysUserMapper sysUserMapper = sqlSession.getMapper(SysUserMapper.class); List<SysRole> sysRoleList = sysUserMapper.selectRolesByUserId(1L); Assert.assertNotNull(sysRoleList); Assert.assertTrue(sysRoleList.size() > 0); } finally { sqlSession.close(); } }
运行该测试方法,输入日志以下。
DEBUG [main] - ==> Preparing: SELECT r.id, r.role_name roleName, r.enabled, r.create_by createBy, r.create_time createTime, u.user_name "sysUser.userName", u.user_email "sysUser.userEmail" 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 WHERE u.id = ?
DEBUG [main] - ==> Parameters: 1(Long)
TRACE [main] - <== Columns: id, roleName, enabled, createBy, createTime, sysUser.userName, sysUser.userEmail
TRACE [main] - <== Row: 1, 管理员, 1, 1, 2019-06-27 18:21:12.0, admin, admin@mybatis.tk
TRACE [main] - <== Row: 2, 普通用户, 1, 1, 2019-06-27 18:21:12.0, admin, admin@mybatis.tk
DEBUG [main] - <== Total: 2
截止目前,咱们定义的方法都只有1个参数,要么是只有1个基本类型的参数,好比selectById(Long id);。
要么是只有1个对象做为参数,即将多个参数合并成了1个对象。
但有些场景下,好比只有2个参数,没有必要为这2个参数再新建一个对象,好比咱们如今须要根据用户的id和角色的状态来获取用户的全部角色,那么该如何使用呢?
首先,在接口SysUserMapper中添加以下方法。
/** * 根据用户id和角色的enabled状态获取用户的角色 * * @param userId * @param enabled * @return */ List<SysRole> selectRolesByUserIdAndRoleEnabled(Long userId,Integer enabled);
而后,打开对应的SysUserMapper.xml文件,添加以下代码。
<select id="selectRolesByUserIdAndRoleEnabled" resultType="com.zwwhnly.mybatisaction.model.SysRole"> SELECT r.id, r.role_name roleName, r.enabled, r.create_by createBy, r.create_time createTime 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 WHERE u.id = #{userId} AND r.enabled = #{enabled} </select>
在SysUserMapperTest测试类中,添加以下测试方法。
@Test public void testselectRolesByUserIdAndRoleEnabled() { SqlSession sqlSession = getSqlSession(); try { SysUserMapper sysUserMapper = sqlSession.getMapper(SysUserMapper.class); List<SysRole> sysRoleList = sysUserMapper.selectRolesByUserIdAndRoleEnabled(1L, 1); Assert.assertNotNull(sysRoleList); Assert.assertTrue(sysRoleList.size() > 0); } finally { sqlSession.rollback(); sqlSession.close(); } }
运行该测试方法,发现报以下错误。
报错信息中说未找到参数userId,可用的参数是[0,1,param1,param2],也就是说咱们将代码修改成:
WHERE u.id = #{0} AND r.enabled = #{1}
或者修改成:
WHERE u.id = #{param1} AND r.enabled = #{param2}
这么使用是能够测试经过的,不过这样使用,代码阅读起来不够友好,所以并不推荐这么使用。
推荐在接口方法的参数前添加@Param注解,以下所示:
/** * 根据用户id和角色的enabled状态获取用户的角色 * * @param userId * @param enabled * @return */ List<SysRole> selectRolesByUserIdAndRoleEnabled(@Param("userId") Long userId, @Param("enabled") Integer enabled);
运行刚刚添加的测试方法,测试经过,输出日志以下:
DEBUG [main] - ==> Preparing: SELECT r.id, r.role_name roleName, r.enabled, r.create_by createBy, r.create_time createTime 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 WHERE u.id = ? AND r.enabled = ?
DEBUG [main] - ==> Parameters: 1(Long), 1(Integer)
TRACE [main] - <== Columns: id, roleName, enabled, createBy, createTime
TRACE [main] - <== Row: 1, 管理员, 1, 1, 2019-06-27 18:21:12.0
TRACE [main] - <== Row: 2, 普通用户, 1, 1, 2019-06-27 18:21:12.0
DEBUG [main] - <== Total: 2
为了演示参数类型是对象的使用方法,咱们在接口SysUserMapper中添加以下方法:
/** * 根据用户id和角色的enabled状态获取用户的角色 * * @param user * @param role * @return */ List<SysRole> selectRolesByUserAndRole(@Param("user") SysUser user, @Param("role") SysRole role);
此时对应的xml中的语句为:
<select id="selectRolesByUserAndRole" resultType="com.zwwhnly.mybatisaction.model.SysRole"> SELECT r.id, r.role_name roleName, r.enabled, r.create_by createBy, r.create_time createTime 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 WHERE u.id = #{user.id} AND r.enabled = #{role.enabled} </select>
源码地址:https://github.com/zwwhnly/mybatis-action.git,欢迎下载。
刘增辉《MyBatis从入门到精通》
打个小广告,欢迎扫码关注微信公众号:「申城异乡人」,按期分享Java技术干货,让咱们一块儿进步。