0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

MyBatis-Plus为什么不支持联表

汽车电子技术 来源:一行Java 作者:一航 2023-02-28 15:19 次阅读

图片

大家好,我是一航!

早前,写过 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

    文章

    297

    浏览量

    17046
  • 代码
    +关注

    关注

    30

    文章

    4556

    浏览量

    66814
  • mybatis
    +关注

    关注

    0

    文章

    57

    浏览量

    6646
收藏 人收藏

    评论

    相关推荐

    不支持的BIOS?

    PCIe NVMe(M键),它支持上面的UEFI启动和英特尔RST15.5 ..但是当我安装optane时,它在intel optane app ver 16.x上说“不支持的BIOS或BIOS设置
    发表于 10-25 14:58

    CH32V103不支持开源平台吗?

    如题。CH32V103 不支持 J-Link?不支持 Linux 和 macOS 环境?不支持公版 Eclipse、OpenOCD 和 GDB?
    发表于 06-07 11:07

    不支持器件的问题

    我装了Quartus11.0,装了器件库,然后破解了Quartus。可是编译工程,提示破解文件不支持器件。这应该如何解决?谢谢!
    发表于 03-19 14:26

    MCUXpresso不支持Clocks工具吗?

    Pins工具可以使用,但不支持Clocks工具(它被标记为 v11.0)。 能否分享描述此功能何时可用的路线图?
    发表于 05-31 08:54

    苹果iPad不支持繁体中文

    苹果iPad不支持繁体中文     北京时间1月29日消息,美国苹果计算机推出的iPad不支持繁体中文,苹果台湾官方表示:要等
    发表于 01-30 09:50 1015次阅读

    苹果为什么不支持快充!因为太骄傲

    正常来说,一部iPhone 手机使用原装充电器,充电完成需要1.5小时到2小时,而现在很多具备快充技术的手机,那苹果为什么一直不支持快充呢?
    发表于 03-17 09:29 7646次阅读

    网友开喷iPhone8不支持双卡双待 苹果:这锅我不背

    iPhone 8 不支持双卡双待并不是因为苹果偷懒,而是销售 iPhone 的移动运营商的原因。
    发表于 03-21 18:49 2697次阅读

    一篇让你熟练掌握 MyBatis-Plus

    MyBatis-plus 是一款 Mybatis 增强工具,用于简化开发,提高效率。下文使用缩写 mp来简化表示 MyBatis-plus,本文主要介绍 mp 搭配 Spring Boot
    的头像 发表于 06-01 09:30 2368次阅读
    一篇让你熟练掌握 <b class='flag-5'>MyBatis-Plus</b>!

    openharmony不支持安卓吗

    前面议论纷纷的鸿蒙是安卓套壳时代话题结束了,现在,openharmony 支不支持安卓系统的话题又出现了?那么,openharmony 到底支不支持安卓系统呢?
    的头像 发表于 06-23 09:43 1785次阅读

    华为p50为什么不支持5g

    华为p50为什么不支持5g?这是近日广大网友用户吐槽的一个问题,华为已经于近日正式发布了华为p50系列,并将全面支持鸿蒙2.0系统,但是为什么却不支持5G呢?
    的头像 发表于 08-01 09:12 6.8w次阅读

    Mybatis-Plus Mybatis增强工具包

    ./oschina_soft/gitee-mybatis-plus.zip
    发表于 06-13 11:34 1次下载
    <b class='flag-5'>Mybatis-Plus</b> <b class='flag-5'>Mybatis</b>增强工具包

    MyBatis-Plus的使用与测试

    本文主要介绍mybatis-plus这款插件,针对springboot用户。包括引入,配置,使用,以及扩展等常用的方面做一个汇总整理,尽量包含大家常用的场景内容。
    的头像 发表于 08-22 11:56 965次阅读

    介绍一款基于Mybatis-Plus的代码自助生成器

    在基于Mybatis的开发模式中,很多开发者还会选择Mybatis-Plus来辅助功能开发,以此提高开发的效率。
    的头像 发表于 05-23 14:16 854次阅读
    介绍一款基于<b class='flag-5'>Mybatis-Plus</b>的代码自助生成器

    如何调优MyBatis 25倍性能

    最近在压测一批接口,发现接口处理速度慢的有点超出预期,感觉很奇怪,后面定位发现是数据库批量保存这块很慢。 这个项目用的是 mybatis-plus,批量保存直接用的是 mybatis-plus 提供的 saveBatch。 我点进去看了下源码,感觉有点不太对劲
    的头像 发表于 05-30 09:56 385次阅读
    如何调优<b class='flag-5'>MyBatis</b> 25倍性能

    你还在手写join联表查询?MyBatis-Plus这样写太香了!

    众所周知,mybatis plus 封装的 mapper 不支持 join,如果需要支持就必须自己去实现。但是对于大部分的业务场景来说,都需要多表 join,要不然就没必要采用关系型数
    的头像 发表于 07-07 10:19 856次阅读
    你还在手写join联表查询?<b class='flag-5'>MyBatis-Plus</b>这样写太香了!