在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称:mybatis-plus-join开源软件地址:https://gitee.com/mhb0409/mybatis-plus-join开源软件介绍:mybatis-plus-joinmybatis-plus-join是mybatis plus的一个多表插件,上手简单,十分钟不到就能学会全部使用方式,只要会用mp就会用这个插件,仅仅依赖了lombok,而且是扩展mp的构造器并非更改原本的构造器,不会对原有项目产生一点点影响,相信大多数项目都有这俩插件,四舍五入就是没依赖。 mybatis-plus-join示例:
关于该插件的一点问题
目前支持大部分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> 版本对应关系(此处只显示对应的最新版本)
版本日志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.0.9 版本
其他版本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的
注意:这几个方法,前面俩参数和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 |
请发表评论