• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

mybatis-plus-join: mybatis-plus的多表插件完全按照mybats plus的用法来做,支持一对 ...

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称:

mybatis-plus-join

开源软件地址:

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

开源软件介绍:

mybatis-plus-join

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

mybatis-plus-join示例:

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

关于该插件的一点问题

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

目前支持大部分mp常用版本

maven坐标

mybatis plus:3.2.0版本依赖地址:

 <dependency>    <groupId>icu.mhb</groupId>    <artifactId>mybatis-plus-join</artifactId>    <version>1.2.0</version> </dependency>

最新版本依赖地址:

 <dependency>    <groupId>icu.mhb</groupId>    <artifactId>mybatis-plus-join</artifactId>    <version>1.0.9</version> </dependency>

版本对应关系(此处只显示对应的最新版本)

标注:*号代表,从起始版本之后都是可以使用的

Mybatis-plusMybatis-plus-join
3.2.01.2.0
3.3.1 - 3.421.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.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 版本

  1. 增加了多对多映射

  2. 去掉了fastJSON依赖

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

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

1.0.9 版本

  1. 更改默认表、字段别名关键字As 为 空格

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

其他版本

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);

一共是四个方法,分别重写于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;@Configurationpublic class MyBatisPlusConfig extends JoinDefaultSqlInjector {    @Override    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {        List<AbstractMethod> methodList = super.getMethodList(mapperClass);        // 自己的自定义方法        return methodList;    }}

然后就可以愉快的使用了

自定义查询字段和表别名关键字

// 为何要这个东西,因为在不同数据库之间,别名关键字不一样,例如Mysql表别名是 As 而oracle中 是 is 关键字所以需要// 以oracle 关键字为例// 解释一下为什么要这样声明,因为注入器在启动的时候就进行初始化,所以这个构建需要在初始化之前,最简单的办法就是在注入MybatisPlusPropertiesCustomizer的地方进行实例化 @Beanpublic MybatisPlusPropertiesCustomizer plusPropertiesCustomizer() {      MybatisPlusJoinConfig.builder()                // 查询字段别名关键字                .columnAliasKeyword("as")                // 表、left join、right join、inner join 表别名关键字                .tableAliasKeyword("is")                .build();    return MybatisPlusProperties::getGlobalConfig;}// 运行的SQLSELECT 1 as id FROM users is users LEFT JOIN users_age is users_age ON users_age.id = users.age_id

下面来看构造器的使用:

// 第一步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方法结束wrapper.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_namefrom users users  left join users_age users_age on users_age.id = users.age_idwhere (	users_age.age_name = '95')

是不是就很简单,就和mp的原生的比,就是增加了 join方法啥的

加料用法

OK,来点丝滑的加料用法

一对一查询映射

// 很多时候连表返回的字段很多都相同,所以在每个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 ageIdFROM 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   }  }....]

多对多查询映射

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);// 执行SQLSELECT 		    users_age.age_doc,users_age.age_name,users_age.id,users.user_name,users.user_id,users.create_timeFROM 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"}   ]  }]

返回基础类型数据

// 当我们只需要查询一个字段,例如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"

根据实体不为空的数据查询

// 如果需要根据实体查询可以采用这样的实例化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.end();// 执行查询usersService.joinList(wrapper,UsersVo.class);// 执行SQL select   users.user_id,  users.user_name,  users_age.age_namefrom users users  left join users_age users_age on users_age.id = users.age_idwhere  users.user_id = 1 and users.user_name = 'name啊' and users_age.age_name = '95'

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.end();// 执行查询usersService.joinList(wrapper,UsersVo.class);// 执行SQL select   users_age.age_namefrom users users  left join users_age users_age on users_age.id = users.age_idwhere  users.user_id = 1 and users.user_name = 'name啊' and users_age.age_name = '95'

selectAs() 查询添加别名

/*   selectAs(List<As<T>> columns)   selectAs(SFunction<T, ?> column, String alias)  查询并添加别名*/// 拿起来我们上面用的哪个实例。我现在需要给ageName给个别名 user_age_nameJoinLambdaWrapper<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_namefrom users users  left join users_age users_age on users_age.id = users.age_idwhere (	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");    }).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 mpnbfrom users users  left join users_age users_age on users_age.id = users.age_idwhere (	users_age.age_name = '95') /*	这里需要注意啊,如果selectAs那个地方因为是函数接口,所以值是不可以改变的,如果是可变的那么可以采用	selectAs(Arrays.asList(			new As(UserAge::getAgeName,"user_age_name"),			new As(UserAge::getAgeDoc)	))*/    

selectAll() 查询全部

// selectAll()方法,查询出当前表所有的子段JoinLambdaWrapper<Users> wrapper = new JoinLambdaWrapper<>(Users.class
                      

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap