百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

mybatis-plus-join编码实现Join联表查询,真香!

wptr33 2025-03-06 20:08 21 浏览

众所周知,Mybatis Plus 封装的 mapper 不支持 join,如果需要支持就必须自己去实现。但是对于大部分的业务场景来说,都需要多表 join,要不然就没必要采用关系型数据库了。

那么有没有一种不通过硬 SQL 的形式,通过框架提供 join 能力呢?答案是,可以有,今天专门拉出来再说一下,确实能提高不少的开发效率!

使用方法

仓库地址

https://gitee.com/best_handsome/mybatis-plus-join

安装

  • Maven

    com.github.yulichang
    mybatis-plus-join-boot-starter
    1.4.4
  • Gradle
implementation 'com.github.yulichang:mybatis-plus-join-boot-starter:1.4.4'

或者 clone 代码到本地执行 mvn install,再引入以上依赖。

注意:mybatis plus version >= 3.4.0。

使用

  • mapper继承MPJBaseMapper (必选)
  • service继承MPJBaseService (可选)
  • serviceImpl继承MPJBaseServiceImpl (可选)

核心类MPJLambdaWrapper和MPJQueryWrapper

MPJLambdaWrapper用法

简单的三表查询

class test {
    @Resource
    private UserMapper userMapper;

    void testJoin() {
        //和Mybatis plus一致,MPJLambdaWrapper的泛型必须是主表的泛型,并且要用主表的Mapper来调用
        MPJLambdaWrapper wrapper = new MPJLambdaWrapper()
                .selectAll(UserDO.class)//查询user表全部字段
                .select(UserAddressDO::getTel)//查询user_address tel 字段
                .selectAs(UserAddressDO::getAddress, UserDTO::getUserAddress)//别名 t.address AS userAddress
                .select(AreaDO::getProvince, AreaDO::getCity)
                .leftJoin(UserAddressDO.class, UserAddressDO::getUserId, UserDO::getId)
                .leftJoin(AreaDO.class, AreaDO::getId, UserAddressDO::getAreaId)
                .eq(UserDO::getId, 1)
                .like(UserAddressDO::getTel, "1")
                .gt(UserDO::getId, 5);

        //连表查询 返回自定义ResultType
        List list = userMapper.selectJoinList(UserDTO.class, wrapper);

        //分页查询 (需要启用 mybatis plus 分页插件)
        Page listPage = userMapper.selectJoinPage(new Page<>(2, 10), UserDTO.class, wrapper);
    }
}

对应sql

SELECT  
    t.id, t.name, t.sex, t.head_img, 
    t1.tel, t1.address AS userAddress,
    t2.province, t2.city 
FROM 
    user t 
    LEFT JOIN user_address t1 ON t1.user_id = t.id 
    LEFT JOIN area t2 ON t2.id = t1.area_id 
WHERE (
    t.id = ? 
    AND t1.tel LIKE ? 
    AND t.id > ?)

说明:

  • UserDTO.class 查询结果返回类(resultType)
  • selectAll() 查询指定实体类的全部字段
  • select() 查询指定的字段,支持可变参数,同一个select只能查询相同表的字段
  • selectAs() 字段别名查询,用于数据库字段与业务实体类属性名不一致时使用
  • leftJoin() 参数说明;第一个参数: 参与连表的实体类class 第二个参数: 连表的ON字段,这个属性必须是第一个参数实体类的属性 第三个参数: 参与连表的ON的另一个实体类属性
  • 默认主表别名是t,其他的表别名以先后调用的顺序使用t1,t2,t3....
  • 条件查询,可以查询主表以及参与连接的所有表的字段,全部调用mp原生的方法,正常使用没有sql注入风险

MPJLambdaWrapper 还有很多其他的功能

  • 简单的SQL函数使用:https://gitee.com/best_handsome/mybatis-plus-join/wikis/selectFunc()?sort_id=4082479
  • ON语句多条件支持:https://gitee.com/best_handsome/mybatis-plus-join/wikis/leftJoin?sort_id=3496671

等效于ResultMap


    
    
    
    
        
        
        
        
    

MPJLambdaWrapper其他功能

  • 一对一,一对多使用:https://ylctmh.com/pages/core/lambda/select/selectCollection.html
  • 简单的SQL函数使用:https://ylctmh.com/pages/core/lambda/select/selectFunc.html
  • ON语句多条件支持:https://ylctmh.com/pages/core/lambda/join/leftJoin.html

String形式用法(MPJQueryWrapper)

简单的连表查询

class test {
    @Resource
    private UserMapper userMapper;

    void testJoin() {
        MPJQueryWrapper wrapper = new MPJQueryWrapper()
                .selectAll(UserDO.class)
                .select("addr.tel", "addr.address", "a.province")
                .leftJoin("user_address addr on t.id = addr.user_id")
                .rightJoin("area a on addr.area_id = a.id")
                .like("addr.tel", "1")
                .le("a.province", "1");

        //列表查询
        List list = userMapper.selectJoinList(UserDTO.class, wrapper);

        //分页查询 (需要启用 mybatis plus 分页插件)
        Page listPage = userMapper.selectJoinPage(new Page<>(1, 10), UserDTO.class, wrapper);
    }
}

对应sql

SELECT 
    t.id,
    t.name,
    t.sex,
    t.head_img,
    addr.tel,
    addr.address,
    a.province
FROM 
    user t
    LEFT JOIN user_address addr on t.id = addr.user_id
    RIGHT JOIN area a on addr.area_id = a.id
WHERE (
    addr.tel LIKE ?
    AND a.province <= ?)

说明:

  • UserDTO.class 查询结果类(resultType)
  • selectAll(UserDO.class) 查询主表全部字段(主表实体类)默认主表别名 "t"
  • select() mp的select策略是覆盖,以最后一次为准,这里的策略是追加,可以一直select 主表字段可以用lambda,会自动添加表别名,主表别名默认是 t ,非主表字段必须带别名查询
  • leftJoin() rightJoin() innerJoin() 传sql片段 格式 (表 + 别名 + 关联条件)
  • 条件查询,可以查询主表以及参与连接的所有表的字段,全部调用mp原生的方法,正常使用没有sql注入风险

还可以这么操作,但不建议

class test {
    @Resource
    private UserMapper userMapper;

    void testJoin() {
        List list = userMapper.selectJoinList(UserDTO.class,
                new MPJQueryWrapper()
                        .selectAll(UserDO.class)
                        .select("addr.tel", "addr.address")
                        //行列转换
                        .select("CASE t.sex WHEN '男' THEN '1' ELSE '0' END AS sex")
                        //求和函数
                        .select("sum(a.province) AS province")
                        //自定义数据集
                        .leftJoin("(select * from user_address) addr on t.id = addr.user_id")
                        .rightJoin("area a on addr.area_id = a.id")
                        .like("addr.tel", "1")
                        .le("a.province", "1")
                        .orderByDesc("addr.id"));
    }
}

对应sql

SELECT 
    t.id,
    t.name,
    t.sex,
    t.head_img,
    addr.tel,
    addr.address,
    CASE t.sex WHEN '男' THEN '1' ELSE '0' END AS sex,
    sum(a.province) AS province
FROM 
    user t
    LEFT JOIN (select * from user_address) addr on t.id = addr.user_id
    RIGHT JOIN area a on addr.area_id = a.id
WHERE (
    addr.tel LIKE ?
    AND a.province <= ?)
ORDER BY
    addr.id DESC

这样,我们就能和使用 Mybatis Plus 一样进行表关联操作了!


来源:java版web项目 | 公众号


点击关注,带你了解更多

相关推荐

MySQL进阶五之自动读写分离mysql-proxy

自动读写分离目前,大量现网用户的业务场景中存在读多写少、业务负载无法预测等情况,在有大量读请求的应用场景下,单个实例可能无法承受读取压力,甚至会对业务产生影响。为了实现读取能力的弹性扩展,分担数据库压...

Postgres vs MySQL_vs2022连接mysql数据库

...

3分钟短文 | Laravel SQL筛选两个日期之间的记录,怎么写?

引言今天说一个细分的需求,在模型中,或者使用laravel提供的EloquentORM功能,构造查询语句时,返回位于两个指定的日期之间的条目。应该怎么写?本文通过几个例子,为大家梳理一下。学习时...

一文由浅入深带你完全掌握MySQL的锁机制原理与应用

本文将跟大家聊聊InnoDB的锁。本文比较长,包括一条SQL是如何加锁的,一些加锁规则、如何分析和解决死锁问题等内容,建议耐心读完,肯定对大家有帮助的。为什么需要加锁呢?...

验证Mysql中联合索引的最左匹配原则

后端面试中一定是必问mysql的,在以往的面试中好几个面试官都反馈我Mysql基础不行,今天来着重复习一下自己的弱点知识。在Mysql调优中索引优化又是非常重要的方法,不管公司的大小只要后端项目中用到...

MySQL索引解析(联合索引/最左前缀/覆盖索引/索引下推)

目录1.索引基础...

你会看 MySQL 的执行计划(EXPLAIN)吗?

SQL执行太慢怎么办?我们通常会使用EXPLAIN命令来查看SQL的执行计划,然后根据执行计划找出问题所在并进行优化。用法简介...

MySQL 从入门到精通(四)之索引结构

索引概述索引(index),是帮助MySQL高效获取数据的数据结构(有序),在数据之外,数据库系统还维护者满足特定查询算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构...

mysql总结——面试中最常问到的知识点

mysql作为开源数据库中的榜一大哥,一直是面试官们考察的重中之重。今天,我们来总结一下mysql的知识点,供大家复习参照,看完这些知识点,再加上一些边角细节,基本上能够应付大多mysql相关面试了(...

mysql总结——面试中最常问到的知识点(2)

首先我们回顾一下上篇内容,主要复习了索引,事务,锁,以及SQL优化的工具。本篇文章接着写后面的内容。性能优化索引优化,SQL中索引的相关优化主要有以下几个方面:最好是全匹配。如果是联合索引的话,遵循最...

MySQL基础全知全解!超详细无废话!轻松上手~

本期内容提醒:全篇2300+字,篇幅较长,可搭配饭菜一同“食”用,全篇无废话(除了这句),干货满满,可收藏供后期反复观看。注:MySQL中语法不区分大小写,本篇中...

深入剖析 MySQL 中的锁机制原理_mysql 锁详解

在互联网软件开发领域,MySQL作为一款广泛应用的关系型数据库管理系统,其锁机制在保障数据一致性和实现并发控制方面扮演着举足轻重的角色。对于互联网软件开发人员而言,深入理解MySQL的锁机制原理...

Java 与 MySQL 性能优化:MySQL分区表设计与性能优化全解析

引言在数据库管理领域,随着数据量的不断增长,如何高效地管理和操作数据成为了一个关键问题。MySQL分区表作为一种有效的数据管理技术,能够将大型表划分为多个更小、更易管理的分区,从而提升数据库的性能和可...

MySQL基础篇:DQL数据查询操作_mysql 查

一、基础查询DQL基础查询语法SELECT字段列表FROM表名列表WHERE条件列表GROUPBY分组字段列表HAVING分组后条件列表ORDERBY排序字段列表LIMIT...

MySql:索引的基本使用_mysql索引的使用和原理

一、索引基础概念1.什么是索引?索引是数据库表的特殊数据结构(通常是B+树),用于...