MyBatis从入门到精通(三):MyBatis XML方式的基本用法之多表查询
最近在读刘增辉老师所著的《mybatis从入门到精通》一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸!
1. 多表查询
上篇博客中,我们示例的2个查询都是单表查询,但实际的业务场景肯定是需要多表查询的,比如现在有个需求:
查询某个用户拥有的所有角色。这个需求要涉及到sys_user,sys_user_role,sys_role三张表,如何实现呢?
首先,在sysusermapper接口中定义如下方法。
/** * 根据用户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设置的仍然是单表,即只包含角色表的信息。
如果我希望这个查询语句同时返回sysuser表的user_name字段呢,该如何设置resulttype?
方法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
2. 多个接口参数的用法
2.1 参数类型是基本类型
截止目前,我们定义的方法都只有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
2.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>
3. 源码
源码地址:,欢迎下载。
4. 参考
刘增辉《mybatis从入门到精通》
上一篇: TreeView虚拟化跳转
下一篇: 浅谈IHttpHandler
推荐阅读
-
MyBatis从入门到精通(三):MyBatis XML方式的基本用法之多表查询
-
MyBatis从入门到精通(八):MyBatis动态Sql之foreach标签的用法
-
MyBatis从入门到精通(四):MyBatis XML方式的基本用法之增删改
-
MyBatis从入门到精通(七):MyBatis动态Sql之choose,where,set标签的用法
-
MyBatis从入门到精通(二):MyBatis XML方式的基本用法之Select
-
MyBatis从入门到精通(三):MyBatis XML方式的基本用法之多表查询
-
MyBatis从入门到精通(八):MyBatis动态Sql之foreach标签的用法
-
MyBatis从入门到精通(四):MyBatis XML方式的基本用法之增删改
-
MyBatis从入门到精通(七):MyBatis动态Sql之choose,where,set标签的用法
-
MyBatis从入门到精通(二):MyBatis XML方式的基本用法之Select