大家好,我是一航!
早前,寫過 MyBatis-Plus 的詳細(xì)使用],很多鐵子看了之后,也紛紛用起來了,得到的反饋基本都是:真香!但也時不時的有人會來問,這 MyBatis-Plus 不支持聯(lián)表 ,遇到復(fù)雜查詢依然還是麻煩,怎么辦?其實(shí)我在詳細(xì)的使用教程里面就已經(jīng)說到聯(lián)表解決方案,可能由于文章比較的長,方案又寫的比較的靠后,很多朋友沒留意到,這里就單獨(dú)擰出來說一下;
MyBatis-Plus 要想實(shí)現(xiàn)聯(lián)表查詢,只需要引入一個依賴mybatis-plus-join
,就能完美解決;
準(zhǔn)備
本文,需要你對 MyBatis-Plus 有一定的了解,如果之前一直沒有使用過,可以先看一下這邊文章:MyBatis Plus + 兩款神器,徹底解放雙手
“示例源碼地址:https://github.com/vehang/ehang-spring-boot/tree/main/spring-boot-010-mysql-mybatis-plus (
聯(lián)表查詢所有測試用例全部在Test目錄下)
MyBatis Plus Join
MyBatis Plus Join
一款專門解決MyBatis Plus 關(guān)聯(lián)查詢問題的擴(kuò)展框架,他并不一款全新的框架,而是基于MyBatis Plus
功能的增強(qiáng),所以MyBatis Plus
的所有功能MyBatis Plus Join
同樣擁有;框架的使用方式和MyBatis Plus
一樣簡單,幾行代碼就能實(shí)現(xiàn)聯(lián)表查詢的功能
“官方倉庫:https://gitee.com/best_handsome/mybatis-plus-join
依賴
- mybatis
<dependency> <groupId>com.baomidou<span class="hljs-name"groupId> <artifactId>mybatis-plus-boot-starter<span class="hljs-name"artifactId> <version>3.4.3.4<span class="hljs-name"version> <span class="hljs-name"dependency>
- 數(shù)據(jù)庫連接依賴;
大版本務(wù)必和自己的數(shù)據(jù)庫版本一致<dependency> <groupId>mysql<span class="hljs-name"groupId> <artifactId>mysql-connector-java<span class="hljs-name"artifactId> <version>5.1.46<span class="hljs-name"version> <span class="hljs-name"dependency>
- 分頁
<dependency> <groupId>com.baomidou<span class="hljs-name"groupId> <artifactId>mybatis-plus-extension<span class="hljs-name"artifactId> <version>3.4.1<span class="hljs-name"version> <span class="hljs-name"dependency>
- 聯(lián)表查詢
<dependency> <groupId>com.github.yulichang<span class="hljs-name"groupId> <artifactId>mybatis-plus-join<span class="hljs-name"artifactId> <version>1.3.11<span class="hljs-name"version> <span class="hljs-name"dependency>
數(shù)據(jù)庫表
為了方便做聯(lián)表測試,這里預(yù)先準(zhǔn)備三張表(學(xué)校表、班級表、學(xué)生表),用來做關(guān)聯(lián)查詢測試,sql如下:
DROP TABLE IF EXISTS `school_info`;
CREATE TABLE `school_info` (
`id` int(11) NOT NULL,
`school_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '學(xué)校名稱',
`school_addr` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '學(xué)校地址',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
INSERT INTO `school_info` VALUES (1, 'XXX小學(xué)', 'xx區(qū)xx街道80號');
- ----------------------------------------------------------------
CREATE TABLE `class_info` (
`id` int(11) NOT NULL,
`class_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '名稱',
`class_desc` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '描述',
`school_id` int(11) NOT NULL COMMENT '隸屬的學(xué)校',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
INSERT INTO `class_info` VALUES (1, '一年級1班', NULL, 1);
INSERT INTO `class_info` VALUES (2, '一年級2班', NULL, 1);
- ----------------------------------------------------------------
CREATE TABLE `student_info` (
`id` int(11) NOT NULL,
`name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`age` int(11) NULL DEFAULT NULL,
`class_id` int(11) NULL DEFAULT NULL,
`school_id` int(11) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
INSERT INTO `student_info` VALUES (1, '張三', 7, 1, 1);
INSERT INTO `student_info` VALUES (2, '李四', 7, 2, 1);
INSERT INTO `student_info` VALUES (3, '王五', 8, 1, 1);
INSERT INTO `student_info` VALUES (4, '趙六', 8, 1, 1);
基礎(chǔ) MyBatis Plus 代碼生成
以下的代碼通過 MyBatisX 工具自動生成;可參考 MyBatisX 的插件的使用說明,這里就不再重復(fù)了
MyBatis Plus Join 核心類說明
- MPJBaseMapper
擴(kuò)展了MyBatis Plus的BaseMapper
接口public interface MPJBaseMapper<T> extends BaseMapper<T> { Integer selectJoinCount(@Param("ew") MPJBaseJoin var1); <DTO> DTO selectJoinOne(@Param("resultTypeClass_Eg1sG") Class<DTO> var1, @Param("ew") MPJBaseJoin var2); Map<String, Object> selectJoinMap(@Param("ew") MPJBaseJoin var1); <DTO> List<DTO> selectJoinList(@Param("resultTypeClass_Eg1sG") Class<DTO> var1, @Param("ew") MPJBaseJoin var2); List<Map<String, Object>> selectJoinMaps(@Param("ew") MPJBaseJoin var1); <DTO, P extends IPage?> IPage<DTO> selectJoinPage(P var1, @Param("resultTypeClass_Eg1sG") Class<DTO> var2, @Param("ew") MPJBaseJoin var3); <P extends IPage?> IPage<Map<String, Object>> selectJoinMapsPage(P var1, @Param("ew") MPJBaseJoin var2); }
- MPJBaseService
擴(kuò)展了MyBatis Plus的IService
接口public interface MPJBaseService<T> extends IService<T> { Integer selectJoinCount(MPJBaseJoin var1); <DTO> DTO selectJoinOne(Class<DTO> var1, MPJBaseJoin var2); <DTO> List<DTO> selectJoinList(Class<DTO> var1, MPJBaseJoin var2); <DTO, P extends IPage?> IPage<DTO> selectJoinListPage(P var1, Class<DTO> var2, MPJBaseJoin var3); Map<String, Object> selectJoinMap(MPJBaseJoin var1); List<Map<String, Object>> selectJoinMaps(MPJBaseJoin var1); <P extends IPage<Map<String, Object>>> IPage<Map<String, Object>> selectJoinMapsPage(P var1, MPJBaseJoin var2); }
- MPJBaseServiceImpl
擴(kuò)展了MyBatis Plus的ServiceImpl
接口實(shí)現(xiàn)public class MPJBaseServiceImpl<M extends MPJBaseMapper<T>, T> extends ServiceImpl<M, T> implements MPJBaseService<T> { ... }
整合 MyBatis Plus Join
簡單的三處調(diào)整,就能完成整合工作
-
將mapper改為繼承MPJBaseMapper (必選)
修改前public interface StudentInfoMapper extends BaseMapper<StudentInfo> { }
修改后
public interface StudentInfoMapper extends MPJBaseMapper<StudentInfo> { }
-
將service改為繼承MPJBaseService (可選)
修改前public interface StudentInfoService extends BaseService<StudentInfo> { }
修改后
public interface StudentInfoService extends MPJBaseService<StudentInfo> { }
-
將serviceImpl改為繼承MPJBaseServiceImpl (可選)
修改前@Service public class StudentInfoServiceImpl extends BaseServiceImpl<StudentInfoMapper, StudentInfo> implements StudentInfoService{ }
修改后
@Service public class StudentInfoServiceImpl extends MPJBaseServiceImpl<StudentInfoMapper, StudentInfo> implements StudentInfoService{ }
聯(lián)表測試
測試需求:查詢學(xué)生所處的班級及學(xué)校
DTO定義
用于聯(lián)表查詢后接收數(shù)據(jù)的實(shí)體類
@Data
public class StudentInfoDTO {
// 學(xué)生id
private Integer id;
// 性名
private String name;
// 年齡
private Integer age;
// 班級名稱
private String className;
// 學(xué)校名稱
private String schoolName;
// 學(xué)校地址 用于測試別名
private String scAddr;
}
單記錄聯(lián)表查詢
@Autowired
StudentInfoService sutdentInfoService;
/**
* 聯(lián)表查詢單個
*/
@Test
public void selectJoinOne() {
StudentInfoDTO studentInfoDTO = sutdentInfoService.selectJoinOne(StudentInfoDTO.class,
new MPJLambdaWrapper
簡單說明
- StudentInfoDTO.class
表示resultType,用于接收聯(lián)表查詢之后的數(shù)據(jù)庫返回;“當(dāng)返回是多個表數(shù)據(jù)的整合,需要新定義一個對象用于接收;
當(dāng)返回只需要用到一個表的數(shù)據(jù),直接用數(shù)據(jù)庫映射對象接收即可;
- selectAll
指明查詢實(shí)體對應(yīng)的所有字段 - select
指定查詢列,同一個select只能指明單個表的列,所以多表關(guān)聯(lián)時需要使用多個select去指明不同表的列 - selectAs
重命名,表現(xiàn)在sql層面是會給字段加上as
(別名);主要用在數(shù)據(jù)庫字段名也實(shí)體對象的名稱不一致的情況; - leftJoin、rightJoin、innerJoin
左鏈接、右連接、等值連接;不懂這三種連接方式的,可參考:SQL中 inner join、left join、right join、full join 到底怎么選?詳解來了 -
- 參數(shù)一:參與聯(lián)表的對象
- 參數(shù)二:on關(guān)聯(lián)的指定,此屬性必須是第一個對象中的值
- 參數(shù)三:參與聯(lián)表on的另一個實(shí)體類屬性
- 條件構(gòu)造器
聯(lián)表后可能會存在各種篩選條件,可以根據(jù)上面對條件構(gòu)造器的介紹,指明所需要的篩選條件,比如上面.eq(StudentInfo::getId, 1))
,就是用來指明ID為1的學(xué)生信息。 - 表名
默認(rèn)主表別名是t
,其他的表別名以先后調(diào)用的順序使用 t1,t2,t3.... ;
需要直接apply語句的時候,就得知道對應(yīng)的表名是什么,再進(jìn)行添加,所以不到萬不得已的時候,不建議直接追加語句。
等價SQL
SELECT
t.id,
t.name,
t.age,
t.class_id,
t.school_id,
t1.school_name,
t1.school_addr AS scAddr,
t2.class_name
FROM
student_info t
LEFT JOIN school_info t1 ON (t1.id = t.school_id)
LEFT JOIN class_info t2 ON (t2.id = t.class_id)
WHERE (t.id = ?)
執(zhí)行結(jié)果
多記錄聯(lián)表查詢
@Autowired
StudentInfoService sutdentInfoService;
/**
* 聯(lián)表查詢批量
*/
@Test
public void selectJoinList() {
List
等價SQL
SELECT
t.id,
t.name,
t.age,
t.class_id,
t.school_id,
t1.school_name,
t1.school_addr AS scAddr,
t2.class_name
FROM
student_info t
LEFT JOIN school_info t1 ON (t1.id = t.school_id)
LEFT JOIN class_info t2 ON (t2.id = t.class_id)
執(zhí)行結(jié)果
聯(lián)表分頁查詢
@Autowired
StudentInfoService sutdentInfoService;
/**
* 分頁查詢
*/
@Test
public void selectJoinPage() {
IPage
等價SQL
SELECT
t.id,
t.name,
t.age,
t.class_id,
t.school_id,
t1.school_name,
t1.school_addr AS scAddr,
t2.class_name
FROM
student_info t
LEFT JOIN school_info t1 ON (t1.id = t.school_id)
LEFT JOIN class_info t2 ON (t2.id = t.class_id)
ORDER BY
t.id ASC
LIMIT 2
執(zhí)行結(jié)果
總結(jié)
是不是簡單、方便、好用!
一個依賴,就讓 MyBatis-Plus 擁有聯(lián)表操作,再也不用寫那些繁瑣的xml;不過 MyBatis Plus Join 要求 MyBatis Plus 的版本必須大于等于3.4.0,我在初次整合的時候,確實(shí)就遇到了各種兼容問題,處理了好久,但解決之后,使用起來就變的非常舒服;所以當(dāng)你在決定使用他之前,可以先找一個不太重要的項(xiàng)目,將一些兼容問題先摸索一遍,驗(yàn)證一下方案可行性之后,再進(jìn)一步整合。作者的技術(shù)交流群也比較的活躍,只要有問題,都會給予解答,非常值得一試!
-
框架
+關(guān)注
關(guān)注
0文章
398瀏覽量
17404 -
代碼
+關(guān)注
關(guān)注
30文章
4722瀏覽量
68230 -
mybatis
+關(guān)注
關(guān)注
0文章
58瀏覽量
6695
發(fā)布評論請先 登錄
相關(guān)推薦
評論