mybatis-plus-join mybatis-plus必备神器

引用地址:https://blog.csdn.net/mahuibo123/article/details/125886063

mybatis-plus-join
mybatis-plus-join是mybatis plus的一个多表插件,上手简单,十分钟不到就能学会全部使用方式,只要会用mp就会用这个插件,仅仅依赖了lombok,而且是扩展mp的构造器并非更改原本的构造器,不会对原有项目产生一点点影响,相信大多数项目都有这俩插件,四舍五入就是没依赖。

mybatis-plus-join插件地址:

gitee:https://gitee.com/mhb0409/mybatis-plus-join
github:https://github.com/bobo667/mybatis-plus-join

mybatis-plus-join示例:

gitee: https://gitee.com/mhb0409/mybatis-plus-join-example
github: https://github.com/bobo667/mybatis-plus-join-example

关于该插件的一点问题
出现了bug怎么办,不是mybatis plus官方的会不会不稳定啊? 这个大可以放心,这个插件我已经在生产环境跑了半年多了,没出过什么问题,如果遇到问题可以在 Issues 上提出,我看见就会解决,上午提的,不忙的话下午就能打包新版本,忙的话大概就需要晚上就差不多了
关于维护到啥时候?mybatis plus不倒我不倒(当然,如果长期没有star,哪怕是我得先倒了,还是那,您的star就是作者更新的动力,手动ღ( ´・ᴗ・` )比心)
有什么有想法的新功能啊,或者改善啊,可以在Issues 上提出
如果想联系作者,可以在wx上搜索小程序 马汇博的博客在关于我中有微信号,欢迎来扰
目前支持大部分mp常用版本

maven坐标

mybatis plus:3.2.0版本依赖地址:

 <dependency>
    <groupId>icu.mhb</groupId>
    <artifactId>mybatis-plus-join</artifactId>
    <version>1.2.0</version>
 </dependency>
1
2
3
4
5
最新版本依赖地址:

 <dependency>
    <groupId>icu.mhb</groupId>
    <artifactId>mybatis-plus-join</artifactId>
    <version>1.1.4</version>
 </dependency>
1
2
3
4
5
版本对应关系(此处只显示对应的最新版本)
标注:*号代表,从起始版本之后都是可以使用的

Mybatis-plus    Mybatis-plus-join
3.2.0    1.2.0
3.3.1 - 3.42    1.0.2
3.4.3.4 - *    1.0.3 、1.0.4、1.0.5、1.0.6、1.0.8、1.0.9、1.1.1、1.1.2、1.1.3、1.1.4
版本日志
1.0.1 版本
1.初始化项目 mybatis-plus-join项目诞生

1.0.2 版本
1.优化了selectAs()方法,支持函数简洁式写法

2.增加了缓存优化性能

1.0.3 版本
1.支持3.4.3.4版本

2.增加根据传入实体不为空的数据查询

3.优化了代码逻辑

4.增加notDefaultSelectAll() 不默认查询主表全部的字段

1.0.4 版本
1.支持查询单个参数时候返回单个参数,例如List String

2.优化转换类型的方式

1.0.5 版本
1.修复在没有条件下order 排序失效的问题

1.0.6 版本
1.修复实体条件为主键ID的时候没有加别名问题

2.增加返回值支持一对一查询

1.0.8 版本
增加了多对多映射

去掉了fastJSON依赖

更改serviceImpl动态返回类型的处理方式,采用更优的插件式注入方式

这次终于去掉了总是说的fastJSON依赖,现在采用动态注入resultMap方式,来构建普通多表,一对一,多对多查询,采用插件式懒加载 + 缓存机制,启动时间无影响,使用加载一下就可以直接从缓存调用,保证不影响使用中的效率。

1.0.9 版本
更改默认表、字段别名关键字As 为 空格

增加自定义表、字段别名关键字,在不同数据库中兼容

1.1.1 版本
修复在添加逻辑删除的时候SQL报错问题

返回类型支持Map类型

增加主表和子表自定义别名,方便多个相同子表对应一个主表

这次更新解决了目前使用的一些特殊场景下的缺陷问题,使用的更灵活了

1.1.2 版本
修复逻辑删除没有加别名的问题

修复多个连表情况下,只查询主表的逻辑删除的问题

修复在定义typeHandler不生效的问题

这次更新主要是修复的bug版本,目前作者没有什么特别多的思路去要写什么样的新功能,如果各位有可以提出来

1.1.3 版本
更改逻辑删除出现的条件为join后,而不是where后

Merge pull request !2 from f_ms/N/A

Merge pull request !1 from f_ms/N/A

这次更新主要是修复的bug版本,目前作者没有什么特别多的思路去要写什么样的新功能,如果各位有可以提出来

1.1.4 版本
修复逻辑删除值错误的bug gitee issues-I5UY2K
typeHandler 增加子表支持 gitee issues-I5SUV6
修复 在调用 and()方法的情况下,设置的表别名失效的问题
orderBy 排序增加顺序下标,可根据下标来调整对应的排序顺序
增加 orderBySql 方法,可以手写排序SQL
selectAs 自定义查询字段方法增加重载参数 boolean isQuotes,来标识是否需要是字符,可以用这种方式写一些简单的函数
增加distinct函数方法
优化了代码结构
其他版本
1.2.0 版本
1.支持了3.2.0 版本

废话不多说,直接看怎么使用

   
    /**
     * 查询列表
     *
     * @param wrapper 实体对象封装操作类
     * @param <E>     返回泛型(如果只查询一个字段可以传递String Int之类的类型)
     * @return 返回E 类型的列表
     */
    <EV, E> List<EV> joinList(Wrapper<E> wrapper, Class<EV> clz);

    /**
     * 查询单个对象
     *
     * @param wrapper 实体对象封装操作类
     * @param clz     返回对象 (如果只查询一个字段可以传递String Int之类的类型)
     * @param <E>     包装泛型类型
     * @param <EV>    返回类型泛型
     * @return EV
     */
    <E, EV> EV joinGetOne(Wrapper<E> wrapper, Class<EV> clz);


    /**
     * 查询count
     *
     * @param wrapper 实体对象封装操作类
     * @param <E>     返回泛型
     * @return 总数
     */
    <E> int joinCount(Wrapper<E> wrapper);


    /**
     * 翻页查询
     *
     * @param page    翻页对象
     * @param wrapper 实体对象封装操作类
     */
    <EV, E extends IPage<EV>, C> IPage<EV> joinPage(E page, Wrapper<C> wrapper, Class<EV> clz);


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
一共是四个方法,分别重写于mp的

joinList -> list

joinGetOne -> getOne

joinCount -> count

joinPage -> page

注意:这几个方法,前面俩参数和mp的用法一致,最后一个class类型的是返回类型,这个主要是大多数多表操作都是需要有额外字段,所以需要额外定义,而Wrapper wrapper中的这个需要填写在需要构建条件的实体,这个实体是任意的,不强制,创建条件构造器的时候定义的那个对象就是主表

基本使用方法
1.mapper继承 JoinBaseMapper< T>

2.service继承 JoinIService< T>

3.impl 继承 JoinServiceImpl<M,T>

4.注入mp自定义方法,主要是继承JoinDefaultSqlInjector

package icu.mhb.mpj.example.config;

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import icu.mhb.mybatisplus.plugln.injector.JoinDefaultSqlInjector;
import org.springframework.context.annotation.Configuration;

import java.util.List;

@Configuration
public class MyBatisPlusConfig extends JoinDefaultSqlInjector {

    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
        List<AbstractMethod> methodList = super.getMethodList(mapperClass);
        // 自己的自定义方法
        return methodList;
    }

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
然后就可以愉快的使用了

自定义查询字段和表别名关键字
// 为何要这个东西,因为在不同数据库之间,别名关键字不一样,例如Mysql表别名是 As 而oracle中 是 is 关键字所以需要

// 以oracle 关键字为例
// 解释一下为什么要这样声明,因为注入器在启动的时候就进行初始化,所以这个构建需要在初始化之前,最简单的办法就是在注入MybatisPlusPropertiesCustomizer的地方进行实例化
 @Bean
public MybatisPlusPropertiesCustomizer plusPropertiesCustomizer() {
      MybatisPlusJoinConfig.builder()
                // 查询字段别名关键字
                .columnAliasKeyword("as")
                // 表、left join、right join、inner join 表别名关键字
                .tableAliasKeyword("is")
                .build();
    return MybatisPlusProperties::getGlobalConfig;
}

// 运行的SQL
SELECT 1 as id
 FROM users is users
 LEFT JOIN users_age is users_age
 ON users_age.id = users.age_id

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
自定义函数关键字例如Distinct
// 为何要这个东西,可能有些数据库关键字不一样,他有默认实现,一般情况下不需要传,除非你的数据库真是关键字不一样

// 第一步需要建个类,实现IFuncKeyWord
public class FuncKeyWordImpl implements IFuncKeyWord {
    @Override
    public String distinct() {
        return "distinct";
    }
}

// 第二部在构造器中set进去
JoinLambdaWrapper<Users> wrapper = joinLambdaQueryWrapper(Users.class)
                .setFuncKeyWord(new FuncKeyWordImpl())
  
// 后续会改进为增加全局注入,但是这种方式依旧会保留,避免你多数据源情况下两个数据库查询的关键字都不相同

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
下面来看构造器的使用:

// 第一步new 一个JoinLambdaWrapper构造参数是主表的实体对象(如果在service中直接使用joinLambdaWrapper()方法即可获得)
JoinLambdaWrapper<Users> wrapper = new JoinLambdaWrapper<>(Users.class);

// 第二步 使用leftJoin方法创建一个左连接
/*
    有三个方法可以使用 
    leftJoin 左联
    rightJoin 右联
    innerJoin 内联
*/

// 这一部分一个参数是join中定义的连接的表,第二个参数是随意的表,但是是要出现构造器中的
wrapper.leftJoin(UsersAge.class,UsersAge::getId,Users::getAgeId);
// 然后可以设置多表中的查询条件,这一步和mp一致
wrapper.eq(UserAge::getAgeName,"95")
          .select(UserAge::getAgeName)
      // 最后一步 需要使用end方法结束
      .end();


// 完整的就是
JoinLambdaWrapper<Users> wrapper = new JoinLambdaWrapper<>(Users.class);
wrapper.leftJoin(UsersAge.class,UsersAge::getId,Users::getAgeId)
      .eq(UserAge::getAgeName,"95")
      .select(UserAge::getAgeName)
      .end();

usersService.joinList(wrapper,UsersVo.class);

// 执行SQL 
select 
  users.user_id,
  users.user_name,
  users_age.age_name
from users users
  left join users_age users_age on users_age.id = users.age_id
where (
    users_age.age_name = '95'
)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
是不是就很简单,就和mp的原生的比,就是增加了 join方法啥的

加料用法
OK,来点丝滑的加料用法

orderBy 顺序排列
// 根据index下标进行排列排序顺序 
// @param condition 是否执行 @param isAsc     是否正序
// @param index     下标 @param column    列
orderBy(boolean condition, boolean isAsc, R column, int index) 

// 手写排序SQL @param condition 是否执行  @param sql      SQL
orderBySql(boolean condition, String sql, int index);

JoinLambdaWrapper<Users> wrapper = joinLambdaQueryWrapper(Users.class)
                .orderByDesc(Users::getAgeId) // 如果存在有下标的排序和无下标的排序,无下标的排序,会被存在于最前面
                .leftJoin(UsersAge.class, UsersAge::getId, Users::getAgeId)
                .orderByAsc(UsersAge::getId, 2)
                .orderBySql("users.user_id asc", 0) // 可以手写排序SQL,处理一些复杂的操作,这个orderBySql字表和主表中都可以存在
                .end()
                .orderBySql("users_age.age_name desc", 1);
 return super.joinList(wrapper, UsersVo.class);

// SQL
SELECT users.content_json, users_age.content_json_age as contentJsonAge
FROM users as users
LEFT JOIN users_age as users_age ON users_age.id = users.age_id 
ORDER BY users.age_id DESC,users.user_id asc,users_age.age_name desc,users_age.id ASC;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
distinct 去重
// 根据index下标进行排列排序顺序 
// @param condition 是否执行 @param isAsc     是否正序
// @param index     下标 @param column    列
orderBy(boolean condition, boolean isAsc, R column, int index) 

// 手写排序SQL @param condition 是否执行  @param sql      SQL
orderBySql(boolean condition, String sql, int index);

JoinLambdaWrapper<Users> wrapper = joinLambdaQueryWrapper(Users.class)
                              .distinct() // 这个只能存在于主表
                .orderByDesc(Users::getAgeId) // 如果存在有下标的排序和无下标的排序,无下标的排序,会被存在于最前面
                .leftJoin(UsersAge.class, UsersAge::getId, Users::getAgeId)
                .orderByAsc(UsersAge::getId, 2)
                .orderBySql("users.user_id asc", 0) // 可以手写排序SQL,处理一些复杂的操作,这个orderBySql字表和主表中都可以存在
                .end()
                .orderBySql("users_age.age_name desc", 1);
 return super.joinList(wrapper, UsersVo.class);

// SQL
SELECT DISTINCT users.content_json, users_age.content_json_age as contentJsonAge
FROM users as users
LEFT JOIN users_age as users_age ON users_age.id = users.age_id 
ORDER BY users.age_id DESC,users.user_id asc,users_age.age_name desc,users_age.id ASC;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
自定义别名和返回map类型
// 两个参数代表自定义别名
JoinLambdaWrapper<Users> wrapper = joinLambdaQueryWrapper(Users.class, "userMaster");

wrapper
       .select(Users::getUserId, Users::getUserName)
          // leftJoin innerJoin rightJoin 三个参数代表使用默认别名,四个参数代表使用自定义别名
       .leftJoin(UsersAge.class, UsersAge::getId, Users::getAgeId, "u_age")
       .select(UsersAge::getAgeDoc).end()
       .leftJoin(UsersAge.class, UsersAge::getId, Users::getAgeId, "u_a")
       .select(UsersAge::getAgeName).end();

// 需要注意的是当返回参数为map的时候是没有下划线转驼峰的,如果需要请自行配置mybatis的下划线转驼峰
List<Map> dataList = super.joinList(wrapper, Map.class);

// SQL
SELECT
    userMaster.user_id,
    userMaster.user_name,
    u_age.age_doc,
    u_a.age_name 
FROM
    users AS userMaster
    LEFT JOIN users_age AS u_age ON u_age.id = userMaster.age_id
    LEFT JOIN users_age AS u_a ON u_a.id = userMaster.age_id;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
一对一查询映射
// 很多时候连表返回的字段很多都相同,所以在每个vo里面都会出现,如果把这些重复性字段封装成一个类,会更好维护,所以说针对这个情况 版本 >= 1.0.6 即可使用oneToOneSelect 方法

 JoinLambdaWrapper<Users> wrapper = joinLambdaQueryWrapper(Users.class);

 wrapper.leftJoin(UsersAge.class, UsersAge::getId, Users::getAgeId)
   // oneToOneSelect 第一个参数需要映射的实体类字段,第二个参数则是查询函数
        .oneToOneSelect(UsersVo::getUsersAge, (cb) -> {
             cb.add(UsersAge::getAgeDoc, UsersAge::getAgeName)
               /* 
              当你出现两个实体类映射字段相同,例如 user实体中有个字段id,userAge表中也有个字段id,你                                    想要同时获取这两个字段,这时候则可以使用
               |column : 查询字段
               |alias  : 别名
                             |fieldName : 字段名称
               add(SFunction<T, ?> column, String alias, SFunction<F, ?> fieldName)
               */
               .add(UsersAge::getId, "ageId", UsersAge::getId);
         }).end();

 return super.joinList(wrapper, UsersVo.class);

// 执行SQL 
SELECT users.user_name, users.create_time, users.age_id, users.user_id, users_age.age_doc
    , users_age.age_name, users_age.id AS ageId
FROM users users
    LEFT JOIN users_age users_age ON users_age.id = users.age_id
  
// 返回结果
[
  {
   "ageId":1,
   "createTime":1635416270000,
   "userId":1,
   "userName":"名字啊",
   "usersAge":{
     "ageDoc":"90",
     "ageName":"90",
     "id":1
   }
  }....
]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
多对多查询映射
JoinLambdaWrapper<UsersAge> wrapper = joinLambdaQueryWrapper(UsersAge.class);

wrapper.leftJoin(Users.class, Users::getAgeId, UsersAge::getId)
              // manyToManySelect 多对多,对应的就是 mybatis中的resultMap中的collection标签
              // 该方法第一个参数代表的是需要映射到的实体类字段
        // 第二个参数代表list中的实体类型 例如 List<Users> 这里的实体类型就是Users
              // 第三个就是要查询的字段
        .manyToManySelect(UsersAgesVo::getUsersList, Users.class, (cb) -> {
           cb.add(Users::getUserName, Users::getUserId, Users::getCreateTime);
         }).end();
return super.joinList(wrapper, UsersAgesVo.class);

// 执行SQL
SELECT            
 users_age.age_doc,users_age.age_name,users_age.id,users.user_name,users.user_id,users.create_time
FROM users_age AS users_age
    LEFT JOIN users AS users ON users.age_id = users_age.id;

// 返回数据
[
  {"ageDoc":"90","ageName":"90","id":1,
   "usersList":[
     {"createTime":1635416270000,"userId":1,"userName":"名字啊"},
     {"createTime":1635416270000,"userId":2,"userName":"名字2"}
   ]
  }
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
返回基础类型数据
// 当我们只需要查询一个字段,例如id列表,现在支持直接传递基础类型

JoinLambdaWrapper<Users> wrapper = joinLambdaQueryWrapper(Users.class)
                .select(Users::getUserId);

List<Integer> ids = super.joinList(wrapper, Integer.class);

System.out.println(JSON.toJSONString(ids));

// 输出结果:[1,2]

// 也支持返回单个数据类型

JoinLambdaWrapper<Users> wrapper = joinLambdaQueryWrapper(Users.class)
                .select(Users::getUserName)
                .eq(Users::getUserId, 1)
                .last("limit 1");

String userName = super.joinGetOne(wrapper, String.class);

System.out.println(userName);

// 输出结果:"我是名字1"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
根据实体不为空的数据查询
// 如果需要根据实体查询可以采用这样的实例化
JoinLambdaWrapper<Users> wrapper = new JoinLambdaWrapper<>(new Users().setUserName("name啊")
                                                                          .setUserId(1L));
// 或者可以采用这样的setEntity
// wrapper.setEntity(new Users().setUserName("name啊"));

// 这一部分一个参数是join中定义的连接的表,第二个参数是随意的表,但是是要出现构造器中的
wrapper.leftJoin(UsersAge.class,UsersAge::getId,Users::getAgeId);
// 然后可以设置多表中的查询条件,这一步和mp一致
wrapper.eq(UserAge::getAgeName,"95")
          .select(UserAge::getAgeName);
// 最后一步 需要使用end方法结束
wrapper = wrapper.end();

// 执行查询
usersService.joinList(wrapper,UsersVo.class);

// 执行SQL 
select 
  users.user_id,
  users.user_name,
  users_age.age_name
from users users
  left join users_age users_age on users_age.id = users.age_id
where 
 users.user_id = 1
 and users.user_name = 'name啊'
 and users_age.age_name = '95'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
notDefaultSelectAll() 不默认查询主表全部的字段

// 如果需要根据实体查询可以采用这样的实例化
JoinLambdaWrapper<Users> wrapper = new JoinLambdaWrapper<>(new Users().setUserName("name啊")
                                                                          .setUserId(1L));

// 因为默认是查询主表所有查询字段,如果不需要查询主表全部字段就调用该方法
wrapper.notDefaultSelectAll();

// 这一部分一个参数是join中定义的连接的表,第二个参数是随意的表,但是是要出现构造器中的
wrapper.leftJoin(UsersAge.class,UsersAge::getId,Users::getAgeId);
// 然后可以设置多表中的查询条件,这一步和mp一致
wrapper.eq(UserAge::getAgeName,"95")
          .select(UserAge::getAgeName);
// 最后一步 需要使用end方法结束
wrapper = wrapper.end();

// 执行查询
usersService.joinList(wrapper,UsersVo.class);

// 执行SQL 
select 
  users_age.age_name
from users users
  left join users_age users_age on users_age.id = users.age_id
where 
 users.user_id = 1
 and users.user_name = 'name啊'
 and users_age.age_name = '95'


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
selectAs() 查询添加别名
/* 
  selectAs(List<As<T>> columns) 
  selectAs(SFunction<T, ?> column, String alias)
  查询并添加别名
*/
// 拿起来我们上面用的哪个实例。我现在需要给ageName给个别名 user_age_name
JoinLambdaWrapper<Users> wrapper = new JoinLambdaWrapper<>(Users.class);
wrapper.leftJoin(UsersAge.class,UsersAge::getId,Users::getAgeId)
      .eq(UserAge::getAgeName,"95")
      .selectAs(UserAge::getAgeName,"user_age_name")
      .end();
// 执行查询
usersService.joinList(wrapper,UsersVo.class);

// 执行SQL 
select 
  users.user_id,
    users.user_name,
    users_age.age_name as user_age_name
from users users
  left join users_age users_age on users_age.id = users.age_id
where (
    users_age.age_name = '95'
)
    
// 现在来个高级需求,我需要查询出users_age表中的两个字段并且需要加一个固定值

JoinLambdaWrapper<Users> wrapper = new JoinLambdaWrapper<>(Users.class);
wrapper.join(UsersAge.class)
      .leftJoin(UsersAge::getId,Users::getAgeId)
      .eq(UserAge::getAgeName,"95")
    .selectAs((cb) -> {
      cb.add(UserAge::getAgeName,"user_age_name")
        .add(UserAge::getAgeDoc)
        .add("mp永远滴神","mpnb")
        .add("sum(users_age.id)","ageIdSum",false); // 这个为false就是代表不是字符串,会原样查询
    }).end();
// 执行查询
usersService.joinList(wrapper,UsersVo.class);
 
// 执行SQL 
select 
  users.user_id,
    users.user_name,
    users_age.age_name as user_age_name,
    users_age.age_doc,
    'mp永远滴神' as mpnb,
    sum(users_age.id) as ageIdSum
from users users
  left join users_age users_age on users_age.id = users.age_id
where (
    users_age.age_name = '95'
)

 
/*
    这里需要注意啊,如果selectAs那个地方因为是函数接口,所以值是不可以改变的,如果是可变的那么可以采用
    selectAs(Arrays.asList(
            new As(UserAge::getAgeName,"user_age_name"),
            new As(UserAge::getAgeDoc)
    ))
*/
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
selectAll() 查询全部
// selectAll()方法,查询出当前表所有的子段
JoinLambdaWrapper<Users> wrapper = new JoinLambdaWrapper<>(Users.class);
wrapper.leftJoin(UsersAge.class,UsersAge::getId,Users::getAgeId)
      .eq(UserAge::getAgeName,"95")
      .selectAll().end();
// 执行查询
usersService.joinList(wrapper,UsersVo.class);
 
// 执行SQL 
select 
  users.user_id,
    users.user_name,
    users_age.age_name,
    users_age.age_doc,
    users_age.id
from users users
  left join users_age users_age on users_age.id = users.age_id
where (
    users_age.age_name = '95'
)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
joinAnd() join添加条件
   
/*
        相信有很多情况需要限制join的表的限制条件那么就需要 
    joinAnd(SFunction<T, Object> field, Object val, int index)
*/

JoinLambdaWrapper<Users> wrapper = new JoinLambdaWrapper<>(Users.class);
wrapper.leftJoin(UsersAge.class,UsersAge::getId,Users::getAgeId)
      .joinAnd(UsersAge::getId,1,0) // 需要注意啊,这个最后一个下标是指的第几个join,因为有时候会出现多个连接,附表连接主表,附表的附表连接附表这样子
      .eq(UserAge::getAgeName,"95")
      .selectAs((cb) -> {
      cb.add(UserAge::getAgeName,"user_age_name")
        .add(UserAge::getAgeDoc)
        .add("mp永远滴神","mpnb");
    }).end();
// 执行查询
usersService.joinList(wrapper,UsersVo.class);

// 执行SQL 
select 
  users.user_id,
    users.user_name,
    users_age.age_name as user_age_name,
    users_age.age_doc,
    'mp永远滴神' as mpnb
from users users
  left join users_age users_age on users_age.id = users.age_id and users_age.id = 1
where (
    users_age.age_name = '95'
)
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
同个接口返回任意实体
// 这个就不得不说了,大多数情况下,一个接口是返回一个实体类型的,但是很多情况下,我们有不同的业务需求,所返回的对象也是不一样的,全部加在一个对象中又太臃肿不好维护,所以就需要这个返回任意定制类型
// 使用方法 在最后一个参数中增加上自己的实体类型就行了
List<UsersVo> usersVoList = usersService.joinList(wrapper,UsersVo.class);

1
2
3
4
自定义别名 TableAlias
/*
    这个自定义别名是某些业务下,比如说在项目中构建了SQL啊,之类的,但是构建的SQL别名一般都是固定的达到通用,
    所以需要在实体中增加别名使用@TableAlias注解就行了,如果没有添加别名 就默认使用表名作为别名 
*/
@TableName("app_users")
@TableAlias("users")
public class Users implements Serializable {
  
}
 
用法注意
1.在使用 join service 一系列方法的时候,所有参数都不能传null

2.这个条件构造器啊,你在join的时候就相当于创建一个新的构造器,你要在这个新的构造器中实现你所有的操作,包括查询,和条件,排序之类的,这样的好处在于,维护好一些,毕竟都放在一起的话,到时候容易迷。

3.您的start是作者更新的动力,如果用的人多的话,可以留言,我会继续更新并适配mp其他版本,如果各位等不了呢,也可以把源码下载下来,放进你的项目中改一下里面的东西。

文章知识点与官方知识档案匹配,可进一步学习
————————————————
版权声明:本文为CSDN博主「博博.」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/mahuibo123/article/details/125886063

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值