MyBatis XML方式的基本用法之多表查詢功能的示例代碼
1. 多表查詢
在之前,我們示例的2個(gè)查詢都是單表查詢,但實(shí)際的業(yè)務(wù)場(chǎng)景肯定是需要多表查詢的,比如現(xiàn)在有個(gè)需求:
查詢某個(gè)用戶擁有的所有角色。這個(gè)需求要涉及到sys_user,sys_user_role,sys_role三張表,如何實(shí)現(xiàn)呢?
首先,在SysUserMapper接口中定義如下方法。
/** * 根據(jù)用戶id獲取角色信息 * * @param userId * @return */ List<SysRole> selectRolesByUserId(Long userId);
然后打開對(duì)應(yīng)的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>
細(xì)心的讀者可能會(huì)發(fā)現(xiàn),我們雖然使用到了多表查詢,但是resultType設(shè)置的仍然是單表,即只包含角色表的信息。
如果我希望這個(gè)查詢語句同時(shí)返回SysUser表的user_name字段呢,該如何設(shè)置resultType?
方法1:直接在SysRole實(shí)體類中添加userName字段。
private String userName;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
此時(shí)resultType不用修改。
方法2:新建擴(kuò)展類,在擴(kuò)展類中添加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;
}
}
此時(shí)需要將resultType修改為:com.zwwhnly.mybatisaction.model.SysRoleExtend。
這種方式比較適合需要少量額外字段的場(chǎng)景。如果需要其他表的大量字段,可以使用方式3或者方式4,個(gè)人推薦使用方式4。
方法3:在SysRole實(shí)體類中添加SysUser類型的字段。
private SysUser sysUser;
public SysUser getSysUser() {
return sysUser;
}
public void setSysUser(SysUser sysUser) {
this.sysUser = sysUser;
}
此時(shí)resultType不用修改。
方法4(推薦使用):新建擴(kuò)展類,在擴(kuò)展類中添加SysUser類型的字段。
書中推薦的是方式3,方式4是我個(gè)人認(rèn)為更好的方式,因?yàn)閷?shí)體類一般由工具自動(dòng)生成,增加了字段后,后續(xù)容易忘記導(dǎo)致被覆蓋掉。
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;
}
}
此時(shí)需要將resultType修改為:com.zwwhnly.mybatisaction.model.SysRoleExtend。
此時(shí)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中添加測(cè)試代碼如下。
@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();
}
}
運(yùn)行該測(cè)試方法,輸入日志如下。
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. 多個(gè)接口參數(shù)的用法
2.1 參數(shù)類型是基本類型
截止目前,我們定義的方法都只有1個(gè)參數(shù),要么是只有1個(gè)基本類型的參數(shù),比如selectById(Long id);。
要么是只有1個(gè)對(duì)象作為參數(shù),即將多個(gè)參數(shù)合并成了1個(gè)對(duì)象。
但有些場(chǎng)景下,比如只有2個(gè)參數(shù),沒有必要為這2個(gè)參數(shù)再新建一個(gè)對(duì)象,比如我們現(xiàn)在需要根據(jù)用戶的id和角色的狀態(tài)來獲取用戶的所有角色,那么該如何使用呢?
首先,在接口SysUserMapper中添加如下方法。
/** * 根據(jù)用戶id和角色的enabled狀態(tài)獲取用戶的角色 * * @param userId * @param enabled * @return */ List<SysRole> selectRolesByUserIdAndRoleEnabled(Long userId,Integer enabled);
然后,打開對(duì)應(yīng)的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測(cè)試類中,添加如下測(cè)試方法。
@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();
}
}
運(yùn)行該測(cè)試方法,發(fā)現(xiàn)報(bào)如下錯(cuò)誤。

報(bào)錯(cuò)信息中說未找到參數(shù)userId,可用的參數(shù)是[0,1,param1,param2],也就是說我們將代碼修改為:
WHERE u.id = #{0} AND r.enabled = #{1}
或者修改為:
WHERE u.id = #{param1} AND r.enabled = #{param2}
這么使用是可以測(cè)試通過的,不過這樣使用,代碼閱讀起來不夠友好,因此并不推薦這么使用。
推薦在接口方法的參數(shù)前添加@Param注解,如下所示:
/**
* 根據(jù)用戶id和角色的enabled狀態(tài)獲取用戶的角色
*
* @param userId
* @param enabled
* @return
*/
List<SysRole> selectRolesByUserIdAndRoleEnabled(@Param("userId") Long userId, @Param("enabled") Integer enabled);
運(yùn)行剛剛添加的測(cè)試方法,測(cè)試通過,輸出日志如下:
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 參數(shù)類型是對(duì)象
為了演示參數(shù)類型是對(duì)象的使用方法,我們?cè)诮涌赟ysUserMapper中添加如下方法:
/**
* 根據(jù)用戶id和角色的enabled狀態(tài)獲取用戶的角色
*
* @param user
* @param role
* @return
*/
List<SysRole> selectRolesByUserAndRole(@Param("user") SysUser user, @Param("role") SysRole role);
此時(shí)對(duì)應(yīng)的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. 源碼
源碼地址:https://github.com/zwwhnly/mybatis-action.git,歡迎下載。
總結(jié)
以上所述是小編給大家介紹的MyBatis XML方式的基本用法之多表查詢功能的示例代碼,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
相關(guān)文章
java實(shí)現(xiàn)socket客戶端連接服務(wù)端
本文是個(gè)人剛剛開始學(xué)習(xí)如何通過socket去發(fā)送信息下邊的案例,也是書上的在這留下筆記,最后附上一個(gè)實(shí)例,有需要的小伙伴可以參考下。2015-10-10
談?wù)劄镴AXB和response設(shè)置編碼,解決wechat4j中文亂碼的問題
中文亂碼是每個(gè)程序員都會(huì)遇到的問題,本篇文章主要介紹了談?wù)劄镴AXB和response設(shè)置編碼,解決wechat4j中文亂碼的問題,具有一定的參考價(jià)值,有興趣的可以了解一下。2016-12-12
SpringBoot全局異常與數(shù)據(jù)校驗(yàn)的方法
這篇文章主要介紹了SpringBoot全局異常與數(shù)據(jù)校驗(yàn)的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-11-11
10k+點(diǎn)贊的 SpringBoot 后臺(tái)管理系統(tǒng)教程詳解
這篇文章主要介紹了10k+點(diǎn)贊的 SpringBoot 后臺(tái)管理系統(tǒng)教程詳解,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01
Java 必知必會(huì)的 URL 和 URLConnection使用
這篇文章主要介紹了Java 必知必會(huì)的 URL 和 URLConnection使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
SpringBoot如何通過webjars管理靜態(tài)資源文件夾
這篇文章主要介紹了SpringBoot如何通過webjars管理靜態(tài)資源文件夾,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10

