大家好,我是一航!
早前,写过 MyBatis-Plus 的详细使用],很多铁子看了之后,也纷纷用起来了,得到的反馈基本都是:真香!但也时不时的有人会来问,这 MyBatis-Plus 不支持联表 ,遇到复杂查询依然还是麻烦,怎么办?其实我在详细的使用教程里面就已经说到联表解决方案,可能由于文章比较的长,方案又写的比较的靠后,很多朋友没留意到,这里就单独拧出来说一下;
MyBatis-Plus 要想实现联表查询,只需要引入一个依赖mybatis-plus-join
,就能完美解决;
准备
本文,需要你对 MyBatis-Plus 有一定的了解,如果之前一直没有使用过,可以先看一下这边文章:MyBatis Plus + 两款神器,彻底解放双手
“示例源码地址:https://github.com/vehang/ehang-spring-boot/tree/main/spring-boot-010-mysql-mybatis-plus (
联表查询所有测试用例全部在Test目录下)
MyBatis Plus Join
MyBatis Plus Join
一款专门解决MyBatis Plus 关联查询问题的扩展框架,他并不一款全新的框架,而是基于MyBatis Plus
功能的增强,所以MyBatis Plus
的所有功能MyBatis Plus Join
同样拥有;框架的使用方式和MyBatis Plus
一样简单,几行代码就能实现联表查询的功能
“官方仓库: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>
- 数据库连接依赖;
大版本务必和自己的数据库版本一致<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>
- 联表查询
<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>
数据库表
为了方便做联表测试,这里预先准备三张表(学校表、班级表、学生表),用来做关联查询测试,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 '学校名称',
`school_addr` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '学校地址',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
INSERT INTO `school_info` VALUES (1, 'XXX小学', 'xx区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 '隶属的学校',
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);
基础 MyBatis Plus 代码生成
以下的代码通过 MyBatisX 工具自动生成;可参考 MyBatisX 的插件的使用说明,这里就不再重复了
MyBatis Plus Join 核心类说明
- MPJBaseMapper
扩展了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
扩展了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
扩展了MyBatis Plus的ServiceImpl
接口实现public class MPJBaseServiceImpl<M extends MPJBaseMapper<T>, T> extends ServiceImpl<M, T> implements MPJBaseService<T> { ... }
整合 MyBatis Plus Join
简单的三处调整,就能完成整合工作
-
将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{ }
联表测试
测试需求:查询学生所处的班级及学校
DTO定义
用于联表查询后接收数据的实体类
@Data
public class StudentInfoDTO {
// 学生id
private Integer id;
// 性名
private String name;
// 年龄
private Integer age;
// 班级名称
private String className;
// 学校名称
private String schoolName;
// 学校地址 用于测试别名
private String scAddr;
}
单记录联表查询
@Autowired
StudentInfoService sutdentInfoService;
/**
* 联表查询单个
*/
@Test
public void selectJoinOne() {
StudentInfoDTO studentInfoDTO = sutdentInfoService.selectJoinOne(StudentInfoDTO.class,
new MPJLambdaWrapper
简单说明
- StudentInfoDTO.class
表示resultType,用于接收联表查询之后的数据库返回;“当返回是多个表数据的整合,需要新定义一个对象用于接收;
当返回只需要用到一个表的数据,直接用数据库映射对象接收即可;
- selectAll
指明查询实体对应的所有字段 - select
指定查询列,同一个select只能指明单个表的列,所以多表关联时需要使用多个select去指明不同表的列 - selectAs
重命名,表现在sql层面是会给字段加上as
(别名);主要用在数据库字段名也实体对象的名称不一致的情况; - leftJoin、rightJoin、innerJoin
左链接、右连接、等值连接;不懂这三种连接方式的,可参考:SQL中 inner join、left join、right join、full join 到底怎么选?详解来了 -
- 参数一:参与联表的对象
- 参数二:on关联的指定,此属性必须是第一个对象中的值
- 参数三:参与联表on的另一个实体类属性
- 条件构造器
联表后可能会存在各种筛选条件,可以根据上面对条件构造器的介绍,指明所需要的筛选条件,比如上面.eq(StudentInfo::getId, 1))
,就是用来指明ID为1的学生信息。 - 表名
默认主表别名是t
,其他的表别名以先后调用的顺序使用 t1,t2,t3.... ;
需要直接apply语句的时候,就得知道对应的表名是什么,再进行添加,所以不到万不得已的时候,不建议直接追加语句。
等价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 = ?)
执行结果
多记录联表查询
@Autowired
StudentInfoService sutdentInfoService;
/**
* 联表查询批量
*/
@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)
执行结果
联表分页查询
@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
执行结果
总结
是不是简单、方便、好用!
一个依赖,就让 MyBatis-Plus 拥有联表操作,再也不用写那些繁琐的xml;不过 MyBatis Plus Join 要求 MyBatis Plus 的版本必须大于等于3.4.0,我在初次整合的时候,确实就遇到了各种兼容问题,处理了好久,但解决之后,使用起来就变的非常舒服;所以当你在决定使用他之前,可以先找一个不太重要的项目,将一些兼容问题先摸索一遍,验证一下方案可行性之后,再进一步整合。作者的技术交流群也比较的活跃,只要有问题,都会给予解答,非常值得一试!
-
框架
+关注
关注
0文章
403浏览量
17473 -
代码
+关注
关注
30文章
4779浏览量
68515 -
mybatis
+关注
关注
0文章
60浏览量
6709
发布评论请先 登录
相关推荐
评论