commit e74639c8796e0dd5f65483608fb5cbd8ecedcb8a Author: admin <570810310@qq.com> Date: Wed Jan 27 15:47:08 2021 +0800 first diff --git a/mp-test.sql b/mp-test.sql new file mode 100644 index 0000000..0513ca4 --- /dev/null +++ b/mp-test.sql @@ -0,0 +1,78 @@ +/* + Navicat Premium Data Transfer + + Source Server : rm-bp1f1jf1i3x66k1p6go.mysql.rds.aliyuncs.com + Source Server Type : MySQL + Source Server Version : 50725 + Source Host : rm-bp1f1jf1i3x66k1p6go.mysql.rds.aliyuncs.com:3306 + Source Schema : mp-test + + Target Server Type : MySQL + Target Server Version : 50725 + File Encoding : 65001 + + Date: 27/01/2021 15:29:40 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for area +-- ---------------------------- +DROP TABLE IF EXISTS `area`; +CREATE TABLE `area` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `province` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `city` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `area` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `postcode` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 10004 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of area +-- ---------------------------- +INSERT INTO `area` VALUES (10001, '北京', '北京', '东城区', '10001'); +INSERT INTO `area` VALUES (10002, '上海', '上海', '浦东新区', '20001'); +INSERT INTO `area` VALUES (10003, '浙江省', '杭州市', '西湖区', '30001'); + +-- ---------------------------- +-- Table structure for user +-- ---------------------------- +DROP TABLE IF EXISTS `user`; +CREATE TABLE `user` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `sex` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `head_img` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of user +-- ---------------------------- +INSERT INTO `user` VALUES (1, '张三', '男', 'http://url-zhangsan'); +INSERT INTO `user` VALUES (2, '李四', '女', 'http://url-lisi'); + +-- ---------------------------- +-- Table structure for user_address +-- ---------------------------- +DROP TABLE IF EXISTS `user_address`; +CREATE TABLE `user_address` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) NULL DEFAULT NULL, + `area_id` int(11) NULL DEFAULT NULL, + `tel` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; + +-- ---------------------------- +-- Records of user_address +-- ---------------------------- +INSERT INTO `user_address` VALUES (1, 1, 10001, '13111111111', '天安门'); +INSERT INTO `user_address` VALUES (2, 1, 10002, '13222222222', '东方明珠'); +INSERT INTO `user_address` VALUES (3, 2, 10003, '13333333333', '雷峰塔'); + +SET FOREIGN_KEY_CHECKS = 1; diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..b08d500 --- /dev/null +++ b/pom.xml @@ -0,0 +1,101 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.2.7.RELEASE + + + com.example + demo + 0.0.1-SNAPSHOT + mp + Demo project for Spring Boot + + + 1.8 + + + + + com.alibaba + fastjson + 1.2.75 + + + + mysql + mysql-connector-java + 8.0.23 + + + com.alibaba + druid-spring-boot-starter + 1.2.4 + + + + cglib + cglib + 3.3.0 + + + + + org.projectlombok + lombok + 1.18.16 + compile + + + com.baomidou + mybatis-plus-boot-starter + 3.4.2 + + + com.baomidou + mybatis-plus-generator + + + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + + + + + + + ${artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + + + diff --git a/src/main/java/com/example/mp/MpApplication.java b/src/main/java/com/example/mp/MpApplication.java new file mode 100644 index 0000000..5848914 --- /dev/null +++ b/src/main/java/com/example/mp/MpApplication.java @@ -0,0 +1,13 @@ +package com.example.mp; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MpApplication { + + public static void main(String[] args) { + SpringApplication.run(MpApplication.class, args); + } + +} diff --git a/src/main/java/com/example/mp/business/config/MybatisPlusConfig.java b/src/main/java/com/example/mp/business/config/MybatisPlusConfig.java new file mode 100644 index 0000000..5f0cac7 --- /dev/null +++ b/src/main/java/com/example/mp/business/config/MybatisPlusConfig.java @@ -0,0 +1,25 @@ +package com.example.mp.business.config; + +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * mybatis-plus配置 + * + * @author yulichang + */ +@Configuration +public class MybatisPlusConfig { + + /** + * 启用mybatis-plus分页插件 + */ + @Bean + public MybatisPlusInterceptor paginationInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); + return interceptor; + } +} diff --git a/src/main/java/com/example/mp/business/dto/UserDTO.java b/src/main/java/com/example/mp/business/dto/UserDTO.java new file mode 100644 index 0000000..981b443 --- /dev/null +++ b/src/main/java/com/example/mp/business/dto/UserDTO.java @@ -0,0 +1,25 @@ +package com.example.mp.business.dto; + +import lombok.Data; + +@Data +public class UserDTO { + /** user */ + private Integer id; + /** user */ + private String name; + /** user */ + private String sex; + /** user */ + private String headImg; + /** user_address */ + private String tel; + /** user_address */ + private String address; + /** area */ + private String province; + /** area */ + private String city; + /** area */ + private String area; +} diff --git a/src/main/java/com/example/mp/business/entity/AreaEntity.java b/src/main/java/com/example/mp/business/entity/AreaEntity.java new file mode 100644 index 0000000..659332d --- /dev/null +++ b/src/main/java/com/example/mp/business/entity/AreaEntity.java @@ -0,0 +1,23 @@ +package com.example.mp.business.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.example.mp.mybatis.plus.base.MyBaseEntity; +import lombok.Data; + +@Data +@TableName("area") +public class AreaEntity extends MyBaseEntity { + + @TableId + private Integer id; + + private String province; + + private String city; + + private String area; + + private String postcode; + +} diff --git a/src/main/java/com/example/mp/business/entity/UserAddressEntity.java b/src/main/java/com/example/mp/business/entity/UserAddressEntity.java new file mode 100644 index 0000000..9421db4 --- /dev/null +++ b/src/main/java/com/example/mp/business/entity/UserAddressEntity.java @@ -0,0 +1,22 @@ +package com.example.mp.business.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.example.mp.mybatis.plus.base.MyBaseEntity; +import lombok.Data; + +@Data +@TableName("user_address") +public class UserAddressEntity extends MyBaseEntity { + + @TableId + private Integer id; + + private Integer userId; + + private Integer areaId; + + private String tel; + + private String address; +} diff --git a/src/main/java/com/example/mp/business/entity/UserEntity.java b/src/main/java/com/example/mp/business/entity/UserEntity.java new file mode 100644 index 0000000..23ec10b --- /dev/null +++ b/src/main/java/com/example/mp/business/entity/UserEntity.java @@ -0,0 +1,20 @@ +package com.example.mp.business.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.example.mp.mybatis.plus.base.MyBaseEntity; +import lombok.Data; + +@Data +@TableName("user") +public class UserEntity extends MyBaseEntity { + + @TableId + private Integer id; + + private String name; + + private String sex; + + private String headImg; +} diff --git a/src/main/java/com/example/mp/business/mapper/AreaMapper.java b/src/main/java/com/example/mp/business/mapper/AreaMapper.java new file mode 100644 index 0000000..f19be29 --- /dev/null +++ b/src/main/java/com/example/mp/business/mapper/AreaMapper.java @@ -0,0 +1,9 @@ +package com.example.mp.business.mapper; + +import com.example.mp.business.entity.AreaEntity; +import com.example.mp.mybatis.plus.base.MyBaseMapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface AreaMapper extends MyBaseMapper { +} diff --git a/src/main/java/com/example/mp/business/mapper/UserAddressMapper.java b/src/main/java/com/example/mp/business/mapper/UserAddressMapper.java new file mode 100644 index 0000000..b6b214d --- /dev/null +++ b/src/main/java/com/example/mp/business/mapper/UserAddressMapper.java @@ -0,0 +1,9 @@ +package com.example.mp.business.mapper; + +import com.example.mp.business.entity.UserAddressEntity; +import com.example.mp.mybatis.plus.base.MyBaseMapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface UserAddressMapper extends MyBaseMapper { +} diff --git a/src/main/java/com/example/mp/business/mapper/UserMapper.java b/src/main/java/com/example/mp/business/mapper/UserMapper.java new file mode 100644 index 0000000..10b1403 --- /dev/null +++ b/src/main/java/com/example/mp/business/mapper/UserMapper.java @@ -0,0 +1,9 @@ +package com.example.mp.business.mapper; + +import com.example.mp.business.entity.UserEntity; +import com.example.mp.mybatis.plus.base.MyBaseMapper; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface UserMapper extends MyBaseMapper { +} diff --git a/src/main/java/com/example/mp/business/service/AreaService.java b/src/main/java/com/example/mp/business/service/AreaService.java new file mode 100644 index 0000000..144411d --- /dev/null +++ b/src/main/java/com/example/mp/business/service/AreaService.java @@ -0,0 +1,7 @@ +package com.example.mp.business.service; + +import com.example.mp.business.entity.AreaEntity; +import com.example.mp.mybatis.plus.base.MyBaseService; + +public interface AreaService extends MyBaseService { +} diff --git a/src/main/java/com/example/mp/business/service/UserAddressService.java b/src/main/java/com/example/mp/business/service/UserAddressService.java new file mode 100644 index 0000000..96f7ca9 --- /dev/null +++ b/src/main/java/com/example/mp/business/service/UserAddressService.java @@ -0,0 +1,7 @@ +package com.example.mp.business.service; + +import com.example.mp.business.entity.UserAddressEntity; +import com.example.mp.mybatis.plus.base.MyBaseService; + +public interface UserAddressService extends MyBaseService { +} diff --git a/src/main/java/com/example/mp/business/service/UserService.java b/src/main/java/com/example/mp/business/service/UserService.java new file mode 100644 index 0000000..7f1d719 --- /dev/null +++ b/src/main/java/com/example/mp/business/service/UserService.java @@ -0,0 +1,8 @@ +package com.example.mp.business.service; + +import com.example.mp.business.entity.UserEntity; +import com.example.mp.mybatis.plus.base.MyBaseService; + +public interface UserService extends MyBaseService { + +} diff --git a/src/main/java/com/example/mp/business/service/impl/AreaServiceImpl.java b/src/main/java/com/example/mp/business/service/impl/AreaServiceImpl.java new file mode 100644 index 0000000..f0c0173 --- /dev/null +++ b/src/main/java/com/example/mp/business/service/impl/AreaServiceImpl.java @@ -0,0 +1,12 @@ +package com.example.mp.business.service.impl; + +import com.example.mp.business.entity.AreaEntity; +import com.example.mp.business.mapper.AreaMapper; +import com.example.mp.business.service.AreaService; +import com.example.mp.mybatis.plus.base.MyBaseServiceImpl; +import org.springframework.stereotype.Service; + +@Service +public class AreaServiceImpl extends MyBaseServiceImpl implements AreaService { + +} diff --git a/src/main/java/com/example/mp/business/service/impl/UserAddressServiceImpl.java b/src/main/java/com/example/mp/business/service/impl/UserAddressServiceImpl.java new file mode 100644 index 0000000..5f8fa66 --- /dev/null +++ b/src/main/java/com/example/mp/business/service/impl/UserAddressServiceImpl.java @@ -0,0 +1,11 @@ +package com.example.mp.business.service.impl; + +import com.example.mp.business.entity.UserAddressEntity; +import com.example.mp.business.mapper.UserAddressMapper; +import com.example.mp.business.service.UserAddressService; +import com.example.mp.mybatis.plus.base.MyBaseServiceImpl; +import org.springframework.stereotype.Service; + +@Service +public class UserAddressServiceImpl extends MyBaseServiceImpl implements UserAddressService { +} diff --git a/src/main/java/com/example/mp/business/service/impl/UserServiceImpl.java b/src/main/java/com/example/mp/business/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..abd0318 --- /dev/null +++ b/src/main/java/com/example/mp/business/service/impl/UserServiceImpl.java @@ -0,0 +1,12 @@ +package com.example.mp.business.service.impl; + +import com.example.mp.business.entity.UserEntity; +import com.example.mp.business.mapper.UserMapper; +import com.example.mp.business.service.UserService; +import com.example.mp.mybatis.plus.base.MyBaseServiceImpl; +import org.springframework.stereotype.Service; + +@Service +public class UserServiceImpl extends MyBaseServiceImpl implements UserService { + +} diff --git a/src/main/java/com/example/mp/mybatis/plus/base/MyBaseEntity.java b/src/main/java/com/example/mp/mybatis/plus/base/MyBaseEntity.java new file mode 100644 index 0000000..4aa1b39 --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/base/MyBaseEntity.java @@ -0,0 +1,10 @@ +package com.example.mp.mybatis.plus.base; + +/** + * 所有数据库对应的entity类的父类 + * 可以添加 id deleted create_by 等通用字段 + * + * @author yulichang + */ +public class MyBaseEntity { +} diff --git a/src/main/java/com/example/mp/mybatis/plus/base/MyBaseMapper.java b/src/main/java/com/example/mp/mybatis/plus/base/MyBaseMapper.java new file mode 100644 index 0000000..d6aab46 --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/base/MyBaseMapper.java @@ -0,0 +1,62 @@ +package com.example.mp.mybatis.plus.base; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Map; + +/** + * @author yulichang + * @see BaseMapper + */ +public interface MyBaseMapper extends BaseMapper { + + /** + * 连表查询返回一条记录 + * + * @param queryWrapper joinWrapper + * @param clazz 返回对象class + */ + DTO selectJoinOne(@Param(Constants.WRAPPER) Wrapper queryWrapper, Class clazz); + + /** + * 连表查询返回Map + * + * @param queryWrapper joinWrapper + */ + Map selectJoinMap(@Param(Constants.WRAPPER) Wrapper queryWrapper); + + /** + * 连表查询返回记录集合 + * + * @param queryWrapper joinWrapper + * @param clazz 返回对象class + */ + List selectJoinList(@Param(Constants.WRAPPER) Wrapper queryWrapper, Class clazz); + + /** + * 连表查询返回Map集合 + * + * @param queryWrapper joinWrapper + */ + List> selectJoinMaps(@Param(Constants.WRAPPER) Wrapper queryWrapper); + + /** + * 连表查询返回记录集合并分页 + * + * @param queryWrapper joinWrapper + * @param 分页返回对象 + */ + > IPage selectJoinPage(P page, @Param(Constants.WRAPPER) Wrapper queryWrapper, Class clazz); + + /** + * 连表查询返回Map集合并分页 + * + * @param queryWrapper joinWrapper + */ +

> IPage> selectJoinMapsPage(P page, @Param(Constants.WRAPPER) Wrapper queryWrapper); +} diff --git a/src/main/java/com/example/mp/mybatis/plus/base/MyBaseService.java b/src/main/java/com/example/mp/mybatis/plus/base/MyBaseService.java new file mode 100644 index 0000000..31e2b0d --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/base/MyBaseService.java @@ -0,0 +1,91 @@ +package com.example.mp.mybatis.plus.base; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.example.mp.mybatis.plus.func.MyWrapperFunc; +import com.example.mp.mybatis.plus.wrapper.MyLambdaQueryWrapper; + +import java.util.List; +import java.util.Map; + +/** + * @author yulichang + * @see IService + */ +public interface MyBaseService extends IService { + + /** + * ignore + */ + default DTO selectJoinOne(MyWrapperFunc wrapperFunc, Class clazz) { + return selectJoinOne(wrapperFunc.apply(new MyLambdaQueryWrapper<>()), clazz); + } + + /** + * 连接查询返回一条记录 + */ + DTO selectJoinOne(MyLambdaQueryWrapper wrapper, Class clazz); + + /** + * ignore + */ + default List selectJoinList(MyWrapperFunc wrapperFunc, Class clazz) { + return selectJoinList(wrapperFunc.apply(new MyLambdaQueryWrapper<>()), clazz); + } + + /** + * 连接查询返回集合 + */ + List selectJoinList(MyLambdaQueryWrapper wrapper, Class clazz); + + + /** + * ignore + */ + default > IPage selectJoinListPage(P page, MyWrapperFunc wrapperFunc, Class clazz) { + return selectJoinListPage(page, wrapperFunc.apply(new MyLambdaQueryWrapper<>()), clazz); + } + + /** + * 连接查询返回集合并分页 + */ + > IPage selectJoinListPage(P page, MyLambdaQueryWrapper wrapper, Class clazz); + + + /** + * ignore + */ + default Map selectJoinMap(MyWrapperFunc wrapperFunc) { + return selectJoinMap(wrapperFunc.apply(new MyLambdaQueryWrapper<>())); + } + + /** + * 连接查询返回Map + */ + Map selectJoinMap(MyLambdaQueryWrapper wrapper); + + /** + * ignore + */ + default List> selectJoinMaps(MyWrapperFunc wrapperFunc) { + return selectJoinMaps(wrapperFunc.apply(new MyLambdaQueryWrapper<>())); + } + + /** + * 连接查询返回Map集合 + */ + List> selectJoinMaps(MyLambdaQueryWrapper wrapper); + + /** + * ignore + */ + default IPage> selectJoinMapsPage(IPage> page, MyWrapperFunc wrapperFunc) { + return selectJoinMapsPage(page, wrapperFunc.apply(new MyLambdaQueryWrapper<>())); + } + + /** + * 连接查询返回Map集合并分页 + */ + IPage> selectJoinMapsPage(IPage> page, MyLambdaQueryWrapper wrapper); + +} diff --git a/src/main/java/com/example/mp/mybatis/plus/base/MyBaseServiceImpl.java b/src/main/java/com/example/mp/mybatis/plus/base/MyBaseServiceImpl.java new file mode 100644 index 0000000..1a72ed0 --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/base/MyBaseServiceImpl.java @@ -0,0 +1,49 @@ +package com.example.mp.mybatis.plus.base; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.example.mp.mybatis.plus.wrapper.MyLambdaQueryWrapper; + +import java.util.List; +import java.util.Map; + +/** + * @author yulichang + * @see ServiceImpl + */ +public class MyBaseServiceImpl, T extends MyBaseEntity> extends ServiceImpl implements MyBaseService { + + + @Override + public DTO selectJoinOne(MyLambdaQueryWrapper wrapper, Class clazz) { + return baseMapper.selectJoinOne(wrapper, clazz); + + } + + @Override + public List selectJoinList(MyLambdaQueryWrapper wrapper, Class clazz) { + return baseMapper.selectJoinList(wrapper, clazz); + } + + @Override + public > IPage selectJoinListPage(P page, MyLambdaQueryWrapper wrapper, Class clazz) { + return baseMapper.selectJoinPage(page, wrapper, clazz); + } + + @Override + public Map selectJoinMap(MyLambdaQueryWrapper wrapper) { + return baseMapper.selectJoinMap(wrapper); + } + + @Override + public List> selectJoinMaps(MyLambdaQueryWrapper wrapper) { + return baseMapper.selectJoinMaps(wrapper); + } + + @Override + public IPage> selectJoinMapsPage(IPage> page, MyLambdaQueryWrapper wrapper) { + return baseMapper.selectJoinMapsPage(page, wrapper); + } + + +} diff --git a/src/main/java/com/example/mp/mybatis/plus/func/MySFunction.java b/src/main/java/com/example/mp/mybatis/plus/func/MySFunction.java new file mode 100644 index 0000000..409a1ff --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/func/MySFunction.java @@ -0,0 +1,16 @@ +package com.example.mp.mybatis.plus.func; + + +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import com.example.mp.mybatis.plus.base.MyBaseEntity; + +/** + * 支持别名的 SFunction + * + * @author yulichang + * @see SFunction + */ +@FunctionalInterface +public interface MySFunction extends SFunction { + +} diff --git a/src/main/java/com/example/mp/mybatis/plus/func/MyWrapperFunc.java b/src/main/java/com/example/mp/mybatis/plus/func/MyWrapperFunc.java new file mode 100644 index 0000000..587b413 --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/func/MyWrapperFunc.java @@ -0,0 +1,13 @@ +package com.example.mp.mybatis.plus.func; + +import com.example.mp.mybatis.plus.base.MyBaseEntity; +import com.example.mp.mybatis.plus.wrapper.MyLambdaQueryWrapper; + +/** + * @author yulichang + */ +@FunctionalInterface +public interface MyWrapperFunc { + + MyLambdaQueryWrapper apply(MyLambdaQueryWrapper wrapper); +} diff --git a/src/main/java/com/example/mp/mybatis/plus/injector/MySqlInjector.java b/src/main/java/com/example/mp/mybatis/plus/injector/MySqlInjector.java new file mode 100644 index 0000000..10f32e3 --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/injector/MySqlInjector.java @@ -0,0 +1,29 @@ +package com.example.mp.mybatis.plus.injector; + +import com.baomidou.mybatisplus.core.injector.AbstractMethod; +import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector; +import com.example.mp.mybatis.plus.method.*; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * SQL 注入器 + * + * @see DefaultSqlInjector + */ +@Component +public class MySqlInjector extends DefaultSqlInjector { + + @Override + public List getMethodList(Class mapperClass) { + List list = super.getMethodList(mapperClass); + list.add(new SelectJoinOne()); + list.add(new SelectJoinList()); + list.add(new SelectJoinPage()); + list.add(new SelectJoinMap()); + list.add(new SelectJoinMaps()); + list.add(new SelectJoinMapsPage()); + return list; + } +} diff --git a/src/main/java/com/example/mp/mybatis/plus/interceptor/MyResultInterceptor.java b/src/main/java/com/example/mp/mybatis/plus/interceptor/MyResultInterceptor.java new file mode 100644 index 0000000..16c0a4a --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/interceptor/MyResultInterceptor.java @@ -0,0 +1,93 @@ +package com.example.mp.mybatis.plus.interceptor; + +import com.baomidou.mybatisplus.core.MybatisParameterHandler; +import com.baomidou.mybatisplus.core.toolkit.ClassUtils; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import net.sf.cglib.beans.BeanMap; +import org.apache.ibatis.executor.resultset.DefaultResultSetHandler; +import org.apache.ibatis.executor.resultset.ResultSetHandler; +import org.apache.ibatis.plugin.*; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Field; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * 结果封装 + * + * @author yulichang + */ +@Component +@Intercepts({@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})}) +public class MyResultInterceptor implements Interceptor { + + + @Override + public Object intercept(Invocation invocation) throws Throwable { + DefaultResultSetHandler handler = (DefaultResultSetHandler) invocation.getTarget(); + Object result = invocation.proceed(); + if (Objects.isNull(result)) { + return null; + } + Class val = getFieldVal(handler); + if (val == null) { + return result; + } + if (result instanceof ArrayList) { + List res = new ArrayList<>(); + for (Object i : ((ArrayList) result)) { + if (i instanceof Map) { + res.add(mapToBean((Map) i, val)); + } else { + return result; + } + } + return res; + } else { + return mapToBean((Map) result, val); + } + } + + public static T mapToBean(Map map, Class clazz) { + T bean = ClassUtils.newInstance(clazz); + BeanMap beanMap = BeanMap.create(bean); + map.forEach((k, v) -> beanMap.put(StringUtils.underlineToCamel(k), v)); + return bean; + } + + + /** + * 反射获取方法中的clazz + * 先用反射获取,应该是可以通过拓展框架直接获取的, todo + * + * @see MybatisParameterHandler + */ + public static Class getFieldVal(DefaultResultSetHandler handler) { + Field[] fieldList = handler.getClass().getDeclaredFields(); + for (Field f : fieldList) { + if (f.getName().equals("parameterHandler")) { + f.setAccessible(true); + try { + MybatisParameterHandler mybatisParameterHandler = (MybatisParameterHandler) f.get(handler); + Object object = mybatisParameterHandler.getParameterObject(); + if (object instanceof Map) { + Map args = (Map) object; + return (Class) args.get("clazz"); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + return null; + } + + @Override + public Object plugin(Object target) { + return Plugin.wrap(target, this); + } +} diff --git a/src/main/java/com/example/mp/mybatis/plus/method/MyAbstractMethod.java b/src/main/java/com/example/mp/mybatis/plus/method/MyAbstractMethod.java new file mode 100644 index 0000000..ae66b5b --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/method/MyAbstractMethod.java @@ -0,0 +1,37 @@ +package com.example.mp.mybatis.plus.method; + +import com.baomidou.mybatisplus.core.injector.AbstractMethod; +import com.baomidou.mybatisplus.core.metadata.TableInfo; +import com.baomidou.mybatisplus.core.toolkit.StringPool; +import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils; +import com.example.mp.mybatis.plus.toolkit.Constant; +import com.example.mp.mybatis.plus.wrapper.MyLambdaQueryWrapper; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author yulichang + * @see AbstractMethod + */ +public abstract class MyAbstractMethod extends AbstractMethod { + + @Override + protected String sqlSelectColumns(TableInfo table, boolean queryWrapper) { + String selectColumns = ASTERISK; + if (table.getResultMap() == null || (table.getResultMap() != null)) { + selectColumns = table.getAllSqlSelect(); + String[] columns = selectColumns.split(StringPool.COMMA); + List selectColumnList = new ArrayList<>(); + for (String c : columns) { + selectColumnList.add(Constant.TABLE_ALIAS + MyLambdaQueryWrapper.TABLE_ALIAS_INDEX + StringPool.DOT + c); + } + selectColumns = String.join(StringPool.COMMA, selectColumnList); + } + if (!queryWrapper) { + return selectColumns; + } + return SqlScriptUtils.convertChoose(String.format("%s != null and %s != null", WRAPPER, Q_WRAPPER_SQL_SELECT), + SqlScriptUtils.unSafeParam(Q_WRAPPER_SQL_SELECT), selectColumns); + } +} diff --git a/src/main/java/com/example/mp/mybatis/plus/method/SelectJoinList.java b/src/main/java/com/example/mp/mybatis/plus/method/SelectJoinList.java new file mode 100644 index 0000000..9db3ea1 --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/method/SelectJoinList.java @@ -0,0 +1,24 @@ +package com.example.mp.mybatis.plus.method; + +import com.baomidou.mybatisplus.core.metadata.TableInfo; +import com.example.mp.mybatis.plus.toolkit.Constant; +import com.example.mp.mybatis.plus.wrapper.MyLambdaQueryWrapper; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.mapping.SqlSource; + +import java.util.Map; + +/** + * copy {@link com.baomidou.mybatisplus.core.injector.methods.SelectMaps} + */ +public class SelectJoinList extends MyAbstractMethod { + + @Override + public MappedStatement injectMappedStatement(Class mapperClass, Class modelClass, TableInfo tableInfo) { + SqlMethod sqlMethod = SqlMethod.SELECT_JOIN_LIST; + String sql = String.format(sqlMethod.getSql(), sqlSelectColumns(tableInfo, true), + tableInfo.getTableName(), Constant.TABLE_ALIAS + MyLambdaQueryWrapper.TABLE_ALIAS_INDEX, sqlWhereEntityWrapper(true, tableInfo), sqlComment()); + SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); + return this.addSelectMappedStatementForOther(mapperClass, sqlMethod.getMethod(), sqlSource, Map.class); + } +} diff --git a/src/main/java/com/example/mp/mybatis/plus/method/SelectJoinMap.java b/src/main/java/com/example/mp/mybatis/plus/method/SelectJoinMap.java new file mode 100644 index 0000000..f8a57b2 --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/method/SelectJoinMap.java @@ -0,0 +1,24 @@ +package com.example.mp.mybatis.plus.method; + +import com.baomidou.mybatisplus.core.metadata.TableInfo; +import com.example.mp.mybatis.plus.toolkit.Constant; +import com.example.mp.mybatis.plus.wrapper.MyLambdaQueryWrapper; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.mapping.SqlSource; + +import java.util.Map; + +/** + * copy {@link com.baomidou.mybatisplus.core.injector.methods.SelectMaps} + */ +public class SelectJoinMap extends MyAbstractMethod { + + @Override + public MappedStatement injectMappedStatement(Class mapperClass, Class modelClass, TableInfo tableInfo) { + SqlMethod sqlMethod = SqlMethod.SELECT_JOIN_MAP; + String sql = String.format(sqlMethod.getSql(), sqlSelectColumns(tableInfo, true), + tableInfo.getTableName(), Constant.TABLE_ALIAS + MyLambdaQueryWrapper.TABLE_ALIAS_INDEX, sqlWhereEntityWrapper(true, tableInfo), sqlComment()); + SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); + return this.addSelectMappedStatementForOther(mapperClass, sqlMethod.getMethod(), sqlSource, Map.class); + } +} diff --git a/src/main/java/com/example/mp/mybatis/plus/method/SelectJoinMaps.java b/src/main/java/com/example/mp/mybatis/plus/method/SelectJoinMaps.java new file mode 100644 index 0000000..036ba32 --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/method/SelectJoinMaps.java @@ -0,0 +1,24 @@ +package com.example.mp.mybatis.plus.method; + +import com.baomidou.mybatisplus.core.metadata.TableInfo; +import com.example.mp.mybatis.plus.toolkit.Constant; +import com.example.mp.mybatis.plus.wrapper.MyLambdaQueryWrapper; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.mapping.SqlSource; + +import java.util.Map; + +/** + * copy {@link com.baomidou.mybatisplus.core.injector.methods.SelectMaps} + */ +public class SelectJoinMaps extends MyAbstractMethod { + + @Override + public MappedStatement injectMappedStatement(Class mapperClass, Class modelClass, TableInfo tableInfo) { + SqlMethod sqlMethod = SqlMethod.SELECT_JOIN_MAPS; + String sql = String.format(sqlMethod.getSql(), sqlSelectColumns(tableInfo, true), + tableInfo.getTableName(), Constant.TABLE_ALIAS + MyLambdaQueryWrapper.TABLE_ALIAS_INDEX, sqlWhereEntityWrapper(true, tableInfo), sqlComment()); + SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); + return this.addSelectMappedStatementForOther(mapperClass, sqlMethod.getMethod(), sqlSource, Map.class); + } +} diff --git a/src/main/java/com/example/mp/mybatis/plus/method/SelectJoinMapsPage.java b/src/main/java/com/example/mp/mybatis/plus/method/SelectJoinMapsPage.java new file mode 100644 index 0000000..96b4fd1 --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/method/SelectJoinMapsPage.java @@ -0,0 +1,24 @@ +package com.example.mp.mybatis.plus.method; + +import com.baomidou.mybatisplus.core.metadata.TableInfo; +import com.example.mp.mybatis.plus.toolkit.Constant; +import com.example.mp.mybatis.plus.wrapper.MyLambdaQueryWrapper; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.mapping.SqlSource; + +import java.util.Map; + +/** + * copy {@link com.baomidou.mybatisplus.core.injector.methods.SelectMaps} + */ +public class SelectJoinMapsPage extends MyAbstractMethod { + + @Override + public MappedStatement injectMappedStatement(Class mapperClass, Class modelClass, TableInfo tableInfo) { + SqlMethod sqlMethod = SqlMethod.SELECT_JOIN_MAPS_PAGE; + String sql = String.format(sqlMethod.getSql(), sqlSelectColumns(tableInfo, true), + tableInfo.getTableName(), Constant.TABLE_ALIAS + MyLambdaQueryWrapper.TABLE_ALIAS_INDEX, sqlWhereEntityWrapper(true, tableInfo), sqlComment()); + SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); + return this.addSelectMappedStatementForOther(mapperClass, sqlMethod.getMethod(), sqlSource, Map.class); + } +} diff --git a/src/main/java/com/example/mp/mybatis/plus/method/SelectJoinOne.java b/src/main/java/com/example/mp/mybatis/plus/method/SelectJoinOne.java new file mode 100644 index 0000000..ec05537 --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/method/SelectJoinOne.java @@ -0,0 +1,24 @@ +package com.example.mp.mybatis.plus.method; + +import com.baomidou.mybatisplus.core.metadata.TableInfo; +import com.example.mp.mybatis.plus.toolkit.Constant; +import com.example.mp.mybatis.plus.wrapper.MyLambdaQueryWrapper; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.mapping.SqlSource; + +import java.util.Map; + +/** + * copy {@link com.baomidou.mybatisplus.core.injector.methods.SelectMaps} + */ +public class SelectJoinOne extends MyAbstractMethod { + + @Override + public MappedStatement injectMappedStatement(Class mapperClass, Class modelClass, TableInfo tableInfo) { + SqlMethod sqlMethod = SqlMethod.SELECT_JOIN_ONE; + String sql = String.format(sqlMethod.getSql(), sqlSelectColumns(tableInfo, true), + tableInfo.getTableName(), Constant.TABLE_ALIAS + MyLambdaQueryWrapper.TABLE_ALIAS_INDEX, sqlWhereEntityWrapper(true, tableInfo), sqlComment()); + SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); + return this.addSelectMappedStatementForOther(mapperClass, sqlMethod.getMethod(), sqlSource, Map.class); + } +} diff --git a/src/main/java/com/example/mp/mybatis/plus/method/SelectJoinPage.java b/src/main/java/com/example/mp/mybatis/plus/method/SelectJoinPage.java new file mode 100644 index 0000000..1c920aa --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/method/SelectJoinPage.java @@ -0,0 +1,24 @@ +package com.example.mp.mybatis.plus.method; + +import com.baomidou.mybatisplus.core.metadata.TableInfo; +import com.example.mp.mybatis.plus.toolkit.Constant; +import com.example.mp.mybatis.plus.wrapper.MyLambdaQueryWrapper; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.mapping.SqlSource; + +import java.util.Map; + +/** + * copy {@link com.baomidou.mybatisplus.core.injector.methods.SelectMaps} + */ +public class SelectJoinPage extends MyAbstractMethod { + + @Override + public MappedStatement injectMappedStatement(Class mapperClass, Class modelClass, TableInfo tableInfo) { + SqlMethod sqlMethod = SqlMethod.SELECT_JOIN_PAGE; + String sql = String.format(sqlMethod.getSql(), sqlSelectColumns(tableInfo, true), + tableInfo.getTableName(), Constant.TABLE_ALIAS + MyLambdaQueryWrapper.TABLE_ALIAS_INDEX, sqlWhereEntityWrapper(true, tableInfo), sqlComment()); + SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); + return this.addSelectMappedStatementForOther(mapperClass, sqlMethod.getMethod(), sqlSource, Map.class); + } +} diff --git a/src/main/java/com/example/mp/mybatis/plus/method/SqlMethod.java b/src/main/java/com/example/mp/mybatis/plus/method/SqlMethod.java new file mode 100644 index 0000000..bf0709c --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/method/SqlMethod.java @@ -0,0 +1,53 @@ +package com.example.mp.mybatis.plus.method; + +/** + * @author yulichang + * @see com.baomidou.mybatisplus.core.enums.SqlMethod + * @since 2021/1/15 + */ +public enum SqlMethod { + + /** + * 连表查询 + */ + SELECT_JOIN_ONE("selectJoinOne", "返回一条记录", + ""), + + SELECT_JOIN_LIST("selectJoinList", "返回List集合", + ""), + + SELECT_JOIN_MAP("selectJoinMap", "返回一个Map", + ""), + + SELECT_JOIN_MAPS("selectJoinMaps", "返回Map集合", + ""), + + SELECT_JOIN_PAGE("selectJoinPage", "连表查询并分页", + ""), + + SELECT_JOIN_MAPS_PAGE("selectJoinMapsPage", "返回Map集合并分页", + ""); + + private final String method; + private final String desc; + private final String sql; + + SqlMethod(String method, String desc, String sql) { + this.method = method; + this.desc = desc; + this.sql = sql; + } + + public String getMethod() { + return method; + } + + public String getDesc() { + return desc; + } + + public String getSql() { + return sql; + } + +} diff --git a/src/main/java/com/example/mp/mybatis/plus/toolkit/Constant.java b/src/main/java/com/example/mp/mybatis/plus/toolkit/Constant.java new file mode 100644 index 0000000..0c98944 --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/toolkit/Constant.java @@ -0,0 +1,42 @@ +package com.example.mp.mybatis.plus.toolkit; + +import com.baomidou.mybatisplus.core.toolkit.StringPool; + +/** + * @author yulichang + */ +public interface Constant { + /** + * 表别名 + */ + String TABLE_ALIAS = "t"; + + String AS = " AS "; + + String ON = " ON "; + + String EQUALS = " = "; + + String JOIN = "JOIN"; + + String LEFT = "LEFT"; + + String RIGHT = "RIGHT"; + + String INNER = "INNER"; + + /** + * " LEFT JOIN " + */ + String LEFT_JOIN = StringPool.SPACE + LEFT + StringPool.SPACE + JOIN + StringPool.SPACE; + + /** + * " RIGHT JOIN " + */ + String RIGHT_JOIN = StringPool.SPACE + RIGHT + StringPool.SPACE + JOIN + StringPool.SPACE; + + /** + * " INNER JOIN " + */ + String INNER_JOIN = StringPool.SPACE + INNER + StringPool.SPACE + JOIN + StringPool.SPACE; +} diff --git a/src/main/java/com/example/mp/mybatis/plus/toolkit/ListJoinUtils.java b/src/main/java/com/example/mp/mybatis/plus/toolkit/ListJoinUtils.java new file mode 100644 index 0000000..4aeedd7 --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/toolkit/ListJoinUtils.java @@ -0,0 +1,166 @@ +package com.example.mp.mybatis.plus.toolkit; + +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.function.BiConsumer; +import java.util.function.BiPredicate; +import java.util.function.Function; + +/** + * 程序连表工具类 + * + * @author yulichang + * @since 2021/01/13 + */ +@Slf4j +public class ListJoinUtils { + + + /** + * List关联 + * example: + * join(leftList, rightList, Left::getRightId, Right::getId, Left::setRight); + *

+ * + * @param leftData 主表 + * @param rightData 数据表 + * @param leftCondition 主表参与比较的属性 + * @param rightCondition 数据表参与比较的属性 + * @param action 主表数据关联操作 + * @param 主表泛型 + * @param 数据表泛型 + * @param 主表参与比较的属性泛型 + * @param 数据表参与比较的属性泛型 + */ + public static void join(List leftData, List rightData, + Function leftCondition, + Function rightCondition, + BiConsumer action) { + if (CollectionUtils.isNotEmpty(leftData) && CollectionUtils.isNotEmpty(rightData)) { + for (L l : leftData) { + LE le = leftCondition.apply(l); + if (Objects.nonNull(le)) { + for (R r : rightData) { + RE re = rightCondition.apply(r); + if (Objects.nonNull(re) && le.equals(re)) { + action.accept(l, r); + break; + } + } + } + } + } + } + + /** + * List关联 + * example: + * join(lefts, rights, (l, r) -> l.getRightId().intValue() == r.getId(), Left::setRight); + *

+ * + * @param leftData 主表 + * @param rightData 数据表 + * @param condition 对比提条件 + * @param action 关联操作 + * @param 主表泛型 + * @param 数据表泛型 + */ + public static void join(List leftData, List rightData, + BiPredicate condition, + BiConsumer action) { + if (CollectionUtils.isNotEmpty(leftData) && CollectionUtils.isNotEmpty(rightData)) { + for (L l : leftData) { + for (R r : rightData) { + if (Objects.nonNull(l) && Objects.nonNull(r)) { + if (condition.test(l, r)) { + action.accept(l, r); + break; + } + } + } + } + } + } + + /** + * List关联 + * example: + *

+ * join(leftList, rightList, (l, r) -> { + * ----if (l.getRightId().intValue() == r.getId()) { + * --------l.setRight(r); + * ----} + * }); + */ + public static void join(List leftData, List rightData, + BiConsumer action) { + if (CollectionUtils.isNotEmpty(leftData) && CollectionUtils.isNotEmpty(rightData)) { + for (L l : leftData) { + for (R r : rightData) { + if (Objects.nonNull(l) && Objects.nonNull(r)) { + action.accept(l, r); + } + } + } + } + } + + /** + * 获取集合中 命中src 的第一条记录的值 + * example + *

+ * leftList.forEach(i -> i.setRightName(findFirst(rightList, i.getRightId(), Right::getId, Right::getName))); + * + * @param collection 数据集合 + * @param src 目标值 + * @param tag 获取目标值的方法 + * @param result 命中结果 + */ + public static R findFirst(Collection collection, Object src, Function tag, Function result) { + if (CollectionUtils.isNotEmpty(collection)) { + for (T t : collection) { + F f = tag.apply(t); + if (Objects.nonNull(f)) { + if (f.equals(src)) { + return result.apply(t); + } + } + } + } + return null; + } + + public static T findFirst(Collection collection, T src) { + if (CollectionUtils.isNotEmpty(collection)) { + for (T t : collection) { + if (t.equals(src)) { + return t; + } + } + } + return null; + } + + /** + * 获取集合中 命中src 的所有记录的值 + */ + public static List findSubList(Collection collection, Object src, Function tag, Function result) { + List r = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(collection)) { + for (T t : collection) { + F f = tag.apply(t); + if (Objects.nonNull(f)) { + if (f.equals(src)) { + r.add(result.apply(t)); + } + } + } + } + return r; + } +} diff --git a/src/main/java/com/example/mp/mybatis/plus/toolkit/MyLambdaUtils.java b/src/main/java/com/example/mp/mybatis/plus/toolkit/MyLambdaUtils.java new file mode 100644 index 0000000..ce99b16 --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/toolkit/MyLambdaUtils.java @@ -0,0 +1,28 @@ +package com.example.mp.mybatis.plus.toolkit; + +import com.baomidou.mybatisplus.core.toolkit.LambdaUtils; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import com.example.mp.mybatis.plus.base.MyBaseEntity; +import com.example.mp.mybatis.plus.func.MySFunction; +import org.apache.ibatis.reflection.property.PropertyNamer; + +/** + * @author yulichang + * @see LambdaUtils + * @see PropertyNamer + */ +public class MyLambdaUtils { + + public static String getName(SFunction fn) { + return PropertyNamer.methodToProperty(LambdaUtils.resolve(fn).getImplMethodName()); + } + + public static String getColumn(MySFunction fn) { + return StringUtils.camelToUnderline(getName(fn)); + } + + public static Class getEntityClass(MySFunction fn) { + return (Class) LambdaUtils.resolve(fn).getImplClass(); + } +} diff --git a/src/main/java/com/example/mp/mybatis/plus/wrapper/MyAbstractLambdaWrapper.java b/src/main/java/com/example/mp/mybatis/plus/wrapper/MyAbstractLambdaWrapper.java new file mode 100644 index 0000000..76d41a2 --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/wrapper/MyAbstractLambdaWrapper.java @@ -0,0 +1,82 @@ +package com.example.mp.mybatis.plus.wrapper; + +import com.baomidou.mybatisplus.core.toolkit.Assert; +import com.baomidou.mybatisplus.core.toolkit.LambdaUtils; +import com.baomidou.mybatisplus.core.toolkit.StringPool; +import com.baomidou.mybatisplus.core.toolkit.support.ColumnCache; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda; +import org.apache.ibatis.reflection.property.PropertyNamer; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import static java.util.stream.Collectors.joining; + +/** + * copy {@link com.baomidou.mybatisplus.core.conditions.AbstractLambdaWrapper} + */ +@SuppressWarnings("serial") +public abstract class MyAbstractLambdaWrapper> + extends MyAbstractWrapper, Children> { + + private Map columnMap = null; + + @SuppressWarnings("unchecked") + @Override + protected String columnsToString(SFunction... columns) { + return columnsToString(true, columns); + } + + @SuppressWarnings("unchecked") + protected String columnsToString(boolean onlyColumn, SFunction... columns) { + return Arrays.stream(columns).map(i -> columnToString(i, onlyColumn)).collect(joining(StringPool.COMMA)); + } + + @Override + protected String columnToString(SFunction column) { + return columnToString(column, true); + } + + protected String columnToString(SFunction column, boolean onlyColumn) { + return getColumn(LambdaUtils.resolve(column), onlyColumn); + } + + protected String column2String(SFunction column, boolean onlyColumn) { + return getColumn(LambdaUtils.resolve(column), onlyColumn); + } + + + /** + * 获取 SerializedLambda 对应的列信息,从 lambda 表达式中推测实体类 + *

+ * 如果获取不到列信息,那么本次条件组装将会失败 + * + * @param lambda lambda 表达式 + * @param onlyColumn 如果是,结果: "name", 如果否: "name" as "name" + * @return 列 + * @throws com.baomidou.mybatisplus.core.exceptions.MybatisPlusException 获取不到列信息时抛出异常 + * @see SerializedLambda#getImplClass() + * @see SerializedLambda#getImplMethodName() + */ + private String getColumn(SerializedLambda lambda, boolean onlyColumn) { + Class aClass = lambda.getInstantiatedType(); + tryInitCache(aClass); + String fieldName = PropertyNamer.methodToProperty(lambda.getImplMethodName()); + ColumnCache columnCache = getColumnCache(fieldName, aClass); + return onlyColumn ? columnCache.getColumn() : columnCache.getColumnSelect(); + } + + private void tryInitCache(Class lambdaClass) { + columnMap = LambdaUtils.getColumnMap(lambdaClass); + Assert.notNull(columnMap, "can not find lambda cache for this entity [%s]", lambdaClass.getName()); + } + + private ColumnCache getColumnCache(String fieldName, Class lambdaClass) { + ColumnCache columnCache = columnMap.get(LambdaUtils.formatKey(fieldName)); + Assert.notNull(columnCache, "can not find lambda cache for this property [%s] of entity [%s]", + fieldName, lambdaClass.getName()); + return columnCache; + } +} diff --git a/src/main/java/com/example/mp/mybatis/plus/wrapper/MyAbstractWrapper.java b/src/main/java/com/example/mp/mybatis/plus/wrapper/MyAbstractWrapper.java new file mode 100644 index 0000000..fd696f9 --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/wrapper/MyAbstractWrapper.java @@ -0,0 +1,201 @@ +package com.example.mp.mybatis.plus.wrapper; + +import com.baomidou.mybatisplus.core.conditions.ISqlSegment; +import com.baomidou.mybatisplus.core.conditions.SharedString; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments; +import com.baomidou.mybatisplus.core.toolkit.*; +import com.baomidou.mybatisplus.core.toolkit.sql.StringEscape; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +import static java.util.stream.Collectors.joining; + +/** + * copy {@link com.baomidou.mybatisplus.core.conditions.AbstractWrapper} + */ +@SuppressWarnings({"serial", "unchecked"}) +public abstract class MyAbstractWrapper> extends Wrapper { + + + /** + * 占位符 + */ + protected final Children typedThis = (Children) this; + /** + * 必要度量 + */ + protected AtomicInteger paramNameSeq; + protected Map paramNameValuePairs; + protected SharedString lastSql; + /** + * SQL注释 + */ + protected SharedString sqlComment; + /** + * SQL起始语句 + */ + protected SharedString sqlFirst; + /** + * ß + * 数据库表映射实体类 + */ + private T entity; + protected MergeSegments expression; + /** + * 实体类型(主要用于确定泛型以及取TableInfo缓存) + */ + private Class entityClass; + + @Override + public T getEntity() { + return entity; + } + + public Children setEntity(T entity) { + this.entity = entity; + return typedThis; + } + + public Class getEntityClass() { + if (entityClass == null && entity != null) { + entityClass = (Class) entity.getClass(); + } + return entityClass; + } + + public Children setEntityClass(Class entityClass) { + if (entityClass != null) { + this.entityClass = entityClass; + } + return typedThis; + } + + /** + * 子类返回一个自己的新对象 + */ + protected abstract Children instance(); + + /** + * 格式化SQL + * + * @param sqlStr SQL语句部分 + * @param params 参数集 + * @return sql + */ + protected final String formatSql(String sqlStr, Object... params) { + return formatSqlIfNeed(true, sqlStr, params); + } + + /** + *

+ * 根据需要格式化SQL
+ *
+ * Format SQL for methods: EntityQ.where/and/or...("name={0}", value); + * ALL the {i} will be replaced with #{MPGENVALi}
+ *
+ * ew.where("sample_name={0}", "haha").and("sample_age >{0} + * and sample_age<{1}", 18, 30) TO + * sample_name=#{MPGENVAL1} and sample_age>#{MPGENVAL2} and + * sample_age<#{MPGENVAL3}
+ *

+ * + * @param need 是否需要格式化 + * @param sqlStr SQL语句部分 + * @param params 参数集 + * @return sql + */ + protected final String formatSqlIfNeed(boolean need, String sqlStr, Object... params) { + if (!need || StringUtils.isBlank(sqlStr)) { + return null; + } + if (ArrayUtils.isNotEmpty(params)) { + for (int i = 0; i < params.length; ++i) { + String genParamName = Constants.WRAPPER_PARAM + paramNameSeq.incrementAndGet(); + sqlStr = sqlStr.replace(String.format("{%s}", i), + String.format(Constants.WRAPPER_PARAM_FORMAT, Constants.WRAPPER, genParamName)); + paramNameValuePairs.put(genParamName, params[i]); + } + } + return sqlStr; + } + + /** + * 必要的初始化 + */ + protected void initNeed() { + paramNameSeq = new AtomicInteger(0); + paramNameValuePairs = new HashMap<>(16); + expression = new MergeSegments(); + lastSql = SharedString.emptyString(); + sqlComment = SharedString.emptyString(); + sqlFirst = SharedString.emptyString(); + } + + @Override + public void clear() { + entity = null; + paramNameSeq.set(0); + paramNameValuePairs.clear(); + expression.clear(); + lastSql.toEmpty(); + sqlComment.toEmpty(); + sqlFirst.toEmpty(); + } + + @Override + public String getSqlSegment() { + return expression.getSqlSegment() + lastSql.getStringValue(); + } + + @Override + public String getSqlComment() { + if (StringUtils.isNotBlank(sqlComment.getStringValue())) { + return "/*" + StringEscape.escapeRawString(sqlComment.getStringValue()) + "*/"; + } + return null; + } + + @Override + public String getSqlFirst() { + if (StringUtils.isNotBlank(sqlFirst.getStringValue())) { + return StringEscape.escapeRawString(sqlFirst.getStringValue()); + } + return null; + } + + @Override + public MergeSegments getExpression() { + return expression; + } + + public Map getParamNameValuePairs() { + return paramNameValuePairs; + } + + /** + * 获取 columnName + */ + protected String columnToString(R column) { + return (String) column; + } + + /** + * 多字段转换为逗号 "," 分割字符串 + * + * @param columns 多字段 + */ + protected String columnsToString(R... columns) { + return Arrays.stream(columns).map(this::columnToString).collect(joining(StringPool.COMMA)); + } + + @Override + @SuppressWarnings("all") + public Children clone() { + return SerializationUtils.clone(typedThis); + } +} diff --git a/src/main/java/com/example/mp/mybatis/plus/wrapper/MyJoinLambdaQueryWrapper.java b/src/main/java/com/example/mp/mybatis/plus/wrapper/MyJoinLambdaQueryWrapper.java new file mode 100644 index 0000000..731b37c --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/wrapper/MyJoinLambdaQueryWrapper.java @@ -0,0 +1,303 @@ +package com.example.mp.mybatis.plus.wrapper; + +import com.baomidou.mybatisplus.core.conditions.SharedString; +import com.baomidou.mybatisplus.core.conditions.query.Query; +import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments; +import com.baomidou.mybatisplus.core.metadata.TableFieldInfo; +import com.baomidou.mybatisplus.core.metadata.TableInfo; +import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; +import com.baomidou.mybatisplus.core.toolkit.ArrayUtils; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import com.example.mp.mybatis.plus.base.MyBaseEntity; +import com.example.mp.mybatis.plus.func.MySFunction; +import com.example.mp.mybatis.plus.toolkit.Constant; +import com.example.mp.mybatis.plus.toolkit.MyLambdaUtils; +import com.example.mp.mybatis.plus.wrapper.interfaces.MyJoin; +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +/** + * 链接查询子Query + * + * @author yulichang + * @see com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper + * @since 2021/01/19 + */ +public class MyJoinLambdaQueryWrapper extends MyAbstractLambdaWrapper> + implements Query, T, SFunction>, MyJoin, T> { + + protected SharedString sqlSelect = new SharedString(); + /** + * select字段 + */ + protected List selectColumnList = new ArrayList<>(); + /** + * 表名 + */ + protected SharedString from = new SharedString(); + /** + * 子表列表 + */ + protected List classList = new ArrayList<>(); + /** + * 表序号 + */ + protected int rUid = 1; + + + public MyJoinLambdaQueryWrapper() { + super.setEntity(null); + super.initNeed(); + } + + public MyJoinLambdaQueryWrapper(int rUid) { + this.rUid = rUid; + super.setEntity(null); + super.initNeed(); + } + + public MyJoinLambdaQueryWrapper(T entity, Class entityClass, SharedString sqlSelect, AtomicInteger paramNameSeq, + Map paramNameValuePairs, MergeSegments mergeSegments, + SharedString lastSql, SharedString sqlComment) { + super.setEntity(entity); + this.setEntityClass(entityClass); + this.paramNameSeq = paramNameSeq; + this.paramNameValuePairs = paramNameValuePairs; + this.expression = mergeSegments; + this.sqlSelect = sqlSelect; + this.lastSql = lastSql; + this.sqlComment = sqlComment; + } + + @Override + protected MyJoinLambdaQueryWrapper instance() { + return new MyJoinLambdaQueryWrapper<>(getEntity(), getEntityClass(), null, paramNameSeq, paramNameValuePairs, + new MergeSegments(), SharedString.emptyString(), SharedString.emptyString()); + } + + @Override + public void clear() { + super.clear(); + this.sqlSelect.toNull(); + this.selectColumnList.clear(); + this.from.toNull(); + this.classList.clear(); + this.rUid = 1; + } + + @Override + public MyJoinLambdaQueryWrapper select(SFunction... columns) { + if (ArrayUtils.isNotEmpty(columns)) { + for (SFunction str : columns) { + selectColumnList.add(new SelectColumn(rUid, columnToString(str), null, null)); + } + } + return typedThis; + } + + /** + * 查询所有字段 (后置处理) + */ + public MyJoinLambdaQueryWrapper selectAll(Class clazz) { + setEntityClass(clazz); + TableInfo info = TableInfoHelper.getTableInfo(getEntityClass()); + info.getFieldList().forEach(s -> + selectColumnList.add(new SelectColumn(this.rUid, s.getColumn(), s.getColumn()/*s.getProperty()*/, null))); + if (StringUtils.isNotBlank(info.getKeyColumn())) { + selectColumnList.add(new SelectColumn(this.rUid, info.getKeyColumn(),info.getKeyColumn()/* info.getKeyProperty()*/, null)); + } + return typedThis; + } + + /** + * 字段去重(同时使用select和as的情况下去除select中重复查询的列,优先使用as列作为查询字段) + * 注意: + * 只对selectDistinct前面的 select selectAll as(asCount ...)有效 + * 只对当前的表去重,对连接查询的其他表不生效,如需要在对应的表下使用此方法 + */ + public MyJoinLambdaQueryWrapper selectDistinct() { + List collect = selectColumnList.stream().filter(i -> i.getUid() == rUid).collect(Collectors.toList()); + List distinctList = new ArrayList<>(); + + List collect1 = collect.stream().distinct().collect(Collectors.toList()); + if (collect.size() != collect1.size()) { + collect.forEach(i -> { + if (!collect1.contains(i)) { + distinctList.add(i); + } + }); + } + for (SelectColumn x : collect1) { + if (x.getAs() != null) { + for (SelectColumn y : collect1) { + if (x.getUid() == y.getUid() && x.getColumn().equals(y.getColumn()) && y.getAs() == null) { + distinctList.add(y); + } + } + } + } + + selectColumnList.removeIf(distinctList::contains); + return this; + } + + @Override + public MyJoinLambdaQueryWrapper select(Predicate predicate) { + return select(getEntityClass(), predicate); + } + + + @Override + public MyJoinLambdaQueryWrapper select(Class entityClass, Predicate predicate) { + this.setEntityClass(entityClass); + TableInfo info = TableInfoHelper.getTableInfo(getEntityClass()); + info.getFieldList().stream().filter(predicate).forEach(s -> + selectColumnList.add(new SelectColumn(this.rUid, s.getColumn(), null, null))); + return typedThis; + } + + + public MyJoinLambdaQueryWrapper as(SFunction entityColumn, SFunction DTOColumn) { + selectColumnList.add(new SelectColumn(rUid, columnToString(entityColumn), MyLambdaUtils.getName(DTOColumn), null)); + return this; + } + + public MyJoinLambdaQueryWrapper asCount(MySFunction entityColumn, SFunction DTOColumn) { + selectColumnList.add(new SelectColumn(rUid, columnToString(entityColumn), MyLambdaUtils.getName(DTOColumn), SelectFunc.COUNT)); + return this; + } + + public MyJoinLambdaQueryWrapper asSum(MySFunction entityColumn, SFunction DTOColumn) { + selectColumnList.add(new SelectColumn(rUid, columnToString(entityColumn), MyLambdaUtils.getName(DTOColumn), SelectFunc.SUM)); + return this; + } + + public MyJoinLambdaQueryWrapper asAvg(MySFunction entityColumn, SFunction DTOColumn) { + selectColumnList.add(new SelectColumn(rUid, columnToString(entityColumn), MyLambdaUtils.getName(DTOColumn), SelectFunc.AVG)); + return this; + } + + public MyJoinLambdaQueryWrapper asMax(MySFunction entityColumn, SFunction DTOColumn) { + selectColumnList.add(new SelectColumn(rUid, columnToString(entityColumn), MyLambdaUtils.getName(DTOColumn), SelectFunc.MAX)); + return this; + } + + public MyJoinLambdaQueryWrapper asMin(MySFunction entityColumn, SFunction DTOColumn) { + selectColumnList.add(new SelectColumn(rUid, columnToString(entityColumn), MyLambdaUtils.getName(DTOColumn), SelectFunc.MIN)); + return this; + } + + public MyJoinLambdaQueryWrapper asDateFormat(MySFunction entityColumn, SFunction DTOColumn) { + selectColumnList.add(new SelectColumn(rUid, columnToString(entityColumn), MyLambdaUtils.getName(DTOColumn), SelectFunc.DATE_FORMAT)); + return this; + } + + /** + * 左连接查询 + * + * @param leftCondition 主表参与比较的字段 (on) + * @param rightCondition 子表参与比较的字段 (on) + * @param rightWrapper 子表的wrapper + */ + @Override + public MyJoinLambdaQueryWrapper leftJoin(boolean condition, String alias, MySFunction leftCondition, MySFunction rightCondition, Function, MyJoinLambdaQueryWrapper> rightWrapper) { + return join(condition, alias, Constant.LEFT_JOIN, leftCondition, rightCondition, rightWrapper); + } + + /** + * 右连接查询(参考左连接) + */ + @Override + public MyJoinLambdaQueryWrapper rightJoin(boolean condition, String alias, MySFunction leftCondition, MySFunction rightCondition, Function, MyJoinLambdaQueryWrapper> rightWrapper) { + return join(condition, alias, Constant.RIGHT_JOIN, leftCondition, rightCondition, rightWrapper); + } + + /** + * 内连接查询(参考左连接) + */ + @Override + public MyJoinLambdaQueryWrapper innerJoin(boolean condition, String alias, MySFunction leftCondition, MySFunction rightCondition, Function, MyJoinLambdaQueryWrapper> rightWrapper) { + return join(condition, alias, Constant.INNER_JOIN, leftCondition, rightCondition, rightWrapper); + } + + private MyJoinLambdaQueryWrapper join(boolean condition, String alias, String keyWord, MySFunction leftCondition, MySFunction rightCondition, Function, MyJoinLambdaQueryWrapper> rightWrapper) { + if (condition) { + setEntityClass(MyLambdaUtils.getEntityClass(leftCondition)); + int childrenId = rUid + 1; + classList.add(new SubTable(alias, keyWord, rUid, MyLambdaUtils.getColumn(leftCondition), childrenId, MyLambdaUtils.getColumn(rightCondition), TableInfoHelper.getTableInfo(MyLambdaUtils.getEntityClass(rightCondition)).getTableName())); + MyJoinLambdaQueryWrapper apply = rightWrapper.apply(new MyJoinLambdaQueryWrapper<>(childrenId)); + classList.addAll(apply.classList); + this.selectColumnList.addAll(apply.selectColumnList); + } + return this; + } + + /** + * 连表条件 + */ + @Data + @AllArgsConstructor + public static class SubTable { + + private String alias; + + private String keyWord; + + private int leftUid; + + private String leftColumn; + + private int rightUid; + + private String rightColumn; + + private String rightTableName; + } + + /** + * select查询字段 + */ + @Data + @AllArgsConstructor + public static class SelectColumn { + + private int uid; + + private String column; + + private String as; + + private SelectFunc function; + + @Override + public boolean equals(Object o) { + if (!(o instanceof SelectColumn)) { + return false; + } + SelectColumn v = (SelectColumn) o; + return v.getUid() == this.uid + && eq(v.getColumn(), this.column) + && eq(v.getAs(), this.as) + && eq(v.getFunction(), this.function); + } + + private boolean eq(Object o1, Object o2) { + if (o1 == null && o2 == null) { + return true; + } + if (o1 == null || o2 == null) { + return false; + } + return o1.equals(o2); + } + } +} diff --git a/src/main/java/com/example/mp/mybatis/plus/wrapper/MyLambdaQueryWrapper.java b/src/main/java/com/example/mp/mybatis/plus/wrapper/MyLambdaQueryWrapper.java new file mode 100644 index 0000000..49a820e --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/wrapper/MyLambdaQueryWrapper.java @@ -0,0 +1,539 @@ +package com.example.mp.mybatis.plus.wrapper; + +import com.baomidou.mybatisplus.core.conditions.ISqlSegment; +import com.baomidou.mybatisplus.core.conditions.SharedString; +import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments; +import com.baomidou.mybatisplus.core.enums.SqlKeyword; +import com.baomidou.mybatisplus.core.enums.SqlLike; +import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException; +import com.baomidou.mybatisplus.core.metadata.TableFieldInfo; +import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; +import com.baomidou.mybatisplus.core.toolkit.ArrayUtils; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.baomidou.mybatisplus.core.toolkit.StringPool; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.core.toolkit.sql.SqlUtils; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import com.example.mp.mybatis.plus.base.MyBaseEntity; +import com.example.mp.mybatis.plus.func.MySFunction; +import com.example.mp.mybatis.plus.toolkit.Constant; +import com.example.mp.mybatis.plus.toolkit.MyLambdaUtils; +import com.example.mp.mybatis.plus.wrapper.interfaces.*; + +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; + +import static com.baomidou.mybatisplus.core.enums.SqlKeyword.*; +import static com.baomidou.mybatisplus.core.enums.WrapperKeyword.APPLY; +import static java.util.stream.Collectors.joining; + +/** + * 连接查询Query + * + * @author yulichang + * @see com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper + * @see com.baomidou.mybatisplus.core.conditions.interfaces.Compare + * @see com.baomidou.mybatisplus.core.conditions.interfaces.Join + * @see com.baomidou.mybatisplus.core.conditions.interfaces.Nested + * @see com.baomidou.mybatisplus.core.conditions.interfaces.Func + * @since 2021/01/19 + */ +public class MyLambdaQueryWrapper extends MyJoinLambdaQueryWrapper + implements MyCompare>, MyNested, MyLambdaQueryWrapper>, + MyFunc> { + + /** + * 表别名初始序号 + */ + public static final int TABLE_ALIAS_INDEX = 0; + + /** + * 主表默认别名 + */ + public static final String DEFAULT_ALIAS = "t"; + + public MyLambdaQueryWrapper() { + this(null); + } + + public MyLambdaQueryWrapper(T entity) { + super.rUid = TABLE_ALIAS_INDEX; + super.setEntity(entity); + super.initNeed(); + } + + MyLambdaQueryWrapper(T entity, Class entityClass, SharedString sqlSelect, AtomicInteger paramNameSeq, + Map paramNameValuePairs, MergeSegments mergeSegments, + SharedString lastSql, SharedString sqlComment, SharedString sqlFirst, + int rUid, List selectColumns, List classList) { + super.setEntity(entity); + super.setEntityClass(entityClass); + this.paramNameSeq = paramNameSeq; + this.paramNameValuePairs = paramNameValuePairs; + this.expression = mergeSegments; + this.sqlSelect = sqlSelect; + this.lastSql = lastSql; + this.sqlComment = sqlComment; + this.sqlFirst = sqlFirst; + this.rUid = rUid; + this.selectColumnList = selectColumns; + this.classList = classList; + } + + @Override + protected MyLambdaQueryWrapper instance() { + return new MyLambdaQueryWrapper<>(getEntity(), getEntityClass(), null, paramNameSeq, paramNameValuePairs, + new MergeSegments(), SharedString.emptyString(), SharedString.emptyString(), SharedString.emptyString(), + rUid, selectColumnList, classList); + } + + + @Override + public MyLambdaQueryWrapper leftJoin(boolean condition, String alias, MySFunction leftCondition, MySFunction rightCondition, Function, MyJoinLambdaQueryWrapper> rightWrapper) { + return join(condition, alias, Constant.LEFT_JOIN, leftCondition, rightCondition, rightWrapper); + } + + @Override + public MyLambdaQueryWrapper leftJoin(MySFunction leftCondition, MySFunction rightCondition, Function, MyJoinLambdaQueryWrapper> rightWrapper) { + return this.leftJoin(true, null, leftCondition, rightCondition, rightWrapper); + } + + @Override + public MyLambdaQueryWrapper leftJoin(String alias, MySFunction leftCondition, MySFunction rightCondition, Function, MyJoinLambdaQueryWrapper> rightWrapper) { + return this.leftJoin(true, alias, leftCondition, rightCondition, rightWrapper); + } + + @Override + public MyLambdaQueryWrapper leftJoin(boolean condition, MySFunction leftCondition, MySFunction rightCondition, Function, MyJoinLambdaQueryWrapper> rightWrapper) { + return this.leftJoin(condition, null, leftCondition, rightCondition, rightWrapper); + } + + public MyLambdaQueryWrapper rightJoin(boolean condition, String alias, MySFunction leftCondition, MySFunction rightCondition, Function, MyJoinLambdaQueryWrapper> rightWrapper) { + return join(condition, alias, Constant.RIGHT_JOIN, leftCondition, rightCondition, rightWrapper); + } + + @Override + public MyLambdaQueryWrapper rightJoin(MySFunction leftCondition, MySFunction rightCondition, Function, MyJoinLambdaQueryWrapper> rightWrapper) { + return this.rightJoin(true, null, leftCondition, rightCondition, rightWrapper); + } + + @Override + public MyLambdaQueryWrapper rightJoin(String alias, MySFunction leftCondition, MySFunction rightCondition, Function, MyJoinLambdaQueryWrapper> rightWrapper) { + return this.rightJoin(true, alias, leftCondition, rightCondition, rightWrapper); + } + + @Override + public MyLambdaQueryWrapper rightJoin(boolean condition, MySFunction leftCondition, MySFunction rightCondition, Function, MyJoinLambdaQueryWrapper> rightWrapper) { + return this.rightJoin(condition, null, leftCondition, rightCondition, rightWrapper); + } + + + public MyLambdaQueryWrapper innerJoin(boolean condition, String alias, MySFunction leftCondition, MySFunction rightCondition, Function, MyJoinLambdaQueryWrapper> rightWrapper) { + return join(condition, alias, Constant.INNER_JOIN, leftCondition, rightCondition, rightWrapper); + } + + @Override + public MyLambdaQueryWrapper innerJoin(MySFunction leftCondition, MySFunction rightCondition, Function, MyJoinLambdaQueryWrapper> rightWrapper) { + return this.innerJoin(true, null, leftCondition, rightCondition, rightWrapper); + } + + @Override + public MyLambdaQueryWrapper innerJoin(String alias, MySFunction leftCondition, MySFunction rightCondition, Function, MyJoinLambdaQueryWrapper> rightWrapper) { + return this.innerJoin(true, alias, leftCondition, rightCondition, rightWrapper); + } + + @Override + public MyLambdaQueryWrapper innerJoin(boolean condition, MySFunction leftCondition, MySFunction rightCondition, Function, MyJoinLambdaQueryWrapper> rightWrapper) { + return this.innerJoin(condition, null, leftCondition, rightCondition, rightWrapper); + } + + private MyLambdaQueryWrapper join(boolean condition, String alias, String keyWord, MySFunction leftCondition, MySFunction rightCondition, Function, MyJoinLambdaQueryWrapper> rightWrapper) { + if (condition) { + setEntityClass(MyLambdaUtils.getEntityClass(leftCondition)); + classList.add(new SubTable(alias, keyWord, rUid, MyLambdaUtils.getColumn(leftCondition), classList.size() + 1, MyLambdaUtils.getColumn(rightCondition), TableInfoHelper.getTableInfo(MyLambdaUtils.getEntityClass(rightCondition)).getTableName())); + MyJoinLambdaQueryWrapper apply = rightWrapper.apply(new MyJoinLambdaQueryWrapper<>(classList.size())); + classList.addAll(apply.classList); + this.selectColumnList.addAll(apply.selectColumnList); + } + return this; + } + + @SafeVarargs + @Override + public final MyLambdaQueryWrapper select(SFunction... columns) { + super.select(columns); + return this; + } + + @Override + public MyLambdaQueryWrapper selectAll(Class clazz) { + super.selectAll(clazz); + return this; + } + + @Override + public MyLambdaQueryWrapper selectDistinct() { + super.selectDistinct(); + return this; + } + + @Override + public MyLambdaQueryWrapper select(Predicate predicate) { + super.select(predicate); + return this; + } + + @Override + public MyLambdaQueryWrapper select(Class entityClass, Predicate predicate) { + super.select(entityClass, predicate); + return this; + } + + @Override + public MyLambdaQueryWrapper as(SFunction entityColumn, SFunction DTOColumn) { + super.as(entityColumn, DTOColumn); + return this; + } + + public MyLambdaQueryWrapper asCount(MySFunction entityColumn, SFunction DTOColumn) { + super.asCount(entityColumn, DTOColumn); + return this; + } + + public MyLambdaQueryWrapper asSum(MySFunction entityColumn, SFunction DTOColumn) { + super.asSum(entityColumn, DTOColumn); + return this; + } + + public MyLambdaQueryWrapper asAvg(MySFunction entityColumn, SFunction DTOColumn) { + super.asAvg(entityColumn, DTOColumn); + return this; + } + + public MyLambdaQueryWrapper asMax(MySFunction entityColumn, SFunction DTOColumn) { + super.asMax(entityColumn, DTOColumn); + return this; + } + + public MyLambdaQueryWrapper asMin(MySFunction entityColumn, SFunction DTOColumn) { + super.asMin(entityColumn, DTOColumn); + return this; + } + + public MyLambdaQueryWrapper asDateFormat(MySFunction entityColumn, SFunction DTOColumn) { + super.asDateFormat(entityColumn, DTOColumn); + return this; + } + + + @Override + public String getSqlSelect() { + if (StringUtils.isBlank(sqlSelect.getStringValue()) && CollectionUtils.isNotEmpty(selectColumnList)) { + List collect = new ArrayList<>(); + selectColumnList.forEach(c -> { + String s = Constant.TABLE_ALIAS + c.getUid() + StringPool.DOT + c.getColumn(); + if (c.getFunction() != null) { + s = String.format(c.getFunction().getSql(), s); + } + if (Objects.isNull(c.getAs())) { + collect.add(s); + } else { + collect.add(s + Constant.AS + c.getAs()); + } + }); + this.sqlSelect.setStringValue(String.join(StringPool.COMMA, collect)); + } + return sqlSelect.getStringValue(); + } + + @Override + public void clear() { + super.clear(); + } + + public String getFrom() { + if (StringUtils.isNotBlank(from.getStringValue())) { + return from.getStringValue(); + } + StringBuilder sb = new StringBuilder(); + this.classList.forEach(right -> + sb.append(right.getKeyWord()).append(right.getRightTableName()) + .append(StringPool.SPACE) + .append(Constant.TABLE_ALIAS) + .append(right.getRightUid()) + .append(Constant.ON) + .append(Constant.TABLE_ALIAS) + .append(right.getLeftUid()) + .append(StringPool.DOT) + .append(right.getLeftColumn()) + .append(Constant.EQUALS) + .append(Constant.TABLE_ALIAS) + .append(right.getRightUid()) + .append(StringPool.DOT) + .append(right.getRightColumn()) + .append(StringPool.SPACE) + ); + this.from.setStringValue(sb.toString()); + return this.from.getStringValue(); + } + + /** + * 获取表前缀 + */ + private String getClassTablePrefix(Class tag) { + if (getEntityClass() == tag) { + return Constant.TABLE_ALIAS + rUid; + } else { + String tableName = TableInfoHelper.getTableInfo(tag).getTableName(); + for (SubTable sub : classList) { + if (sub.getRightTableName().equals(tableName)) { + return Constant.TABLE_ALIAS + sub.getRightUid(); + } + } + } + throw new MybatisPlusException("table not find"); + } + + /** + * 获取column + */ + private String getColumn(MySFunction column, String alias) { + if (alias != null) { + if (alias.equals(DEFAULT_ALIAS)) { + return Constant.TABLE_ALIAS + rUid + StringPool.DOT + column2String(column, true); + } + for (SubTable sub : classList) { + if (alias.equals(sub.getAlias())) { + return Constant.TABLE_ALIAS + sub.getRightUid() + StringPool.DOT + column2String(column, true); + } + } + } + return getClassTablePrefix(MyLambdaUtils.getEntityClass(column)) + StringPool.DOT + column2String(column, true); + } + + private String getColumn(String alias, MySFunction... column) { + return Arrays.stream(column).map(i -> getColumn(i, alias)).collect(joining(StringPool.COMMA)); + } + + @Override + public MyLambdaQueryWrapper eq(boolean condition, String alias, MySFunction column, Object val) { + return doIt(condition, () -> getColumn(column, alias), EQ, + () -> formatSql("{0}", val)); + } + + @Override + public MyLambdaQueryWrapper eq(boolean condition, String alias, MySFunction column, String as, MySFunction val) { + return doIt(condition, () -> getColumn(column, alias), EQ, () -> getColumn(val, as)); + } + + @Override + public MyLambdaQueryWrapper ne(boolean condition, String alias, MySFunction column, Object val) { + return doIt(condition, () -> getColumn(column, alias), NE, () -> formatSql("{0}", val)); + } + + @Override + public MyLambdaQueryWrapper ne(boolean condition, String alias, MySFunction column, String as, MySFunction val) { + return doIt(condition, () -> getColumn(column, alias), NE, () -> getColumn(val, as)); + } + + @Override + public MyLambdaQueryWrapper gt(boolean condition, String alias, MySFunction column, Object val) { + return doIt(condition, () -> getColumn(column, alias), GT, () -> formatSql("{0}", val)); + } + + @Override + public MyLambdaQueryWrapper gt(boolean condition, String alias, MySFunction column, String as, MySFunction val) { + return doIt(condition, () -> getColumn(column, alias), GT, () -> getColumn(val, as)); + } + + @Override + public MyLambdaQueryWrapper ge(boolean condition, String alias, MySFunction column, Object val) { + return doIt(condition, () -> getColumn(column, alias), GE, () -> formatSql("{0}", val)); + } + + @Override + public MyLambdaQueryWrapper ge(boolean condition, String alias, MySFunction column, String as, MySFunction val) { + return doIt(condition, () -> getColumn(column, alias), GE, () -> getColumn(val, as)); + } + + @Override + public MyLambdaQueryWrapper lt(boolean condition, String alias, MySFunction column, Object val) { + return doIt(condition, () -> getColumn(column, alias), LT, () -> formatSql("{0}", val)); + } + + @Override + public MyLambdaQueryWrapper lt(boolean condition, String alias, MySFunction column, String as, MySFunction val) { + return doIt(condition, () -> getColumn(column, alias), LT, () -> getColumn(val, as)); + } + + @Override + public MyLambdaQueryWrapper le(boolean condition, String alias, MySFunction column, Object val) { + return doIt(condition, () -> getColumn(column, alias), LE, () -> formatSql("{0}", val)); + } + + @Override + public MyLambdaQueryWrapper le(boolean condition, String alias, MySFunction column, String as, MySFunction val) { + return doIt(condition, () -> getColumn(column, alias), LE, () -> getColumn(val, as)); + } + + @Override + public MyLambdaQueryWrapper between(boolean condition, String alias, MySFunction column, Object val1, Object val2) { + return doIt(condition, () -> getColumn(column, alias), BETWEEN, () -> formatSql("{0}", val1), AND, + () -> formatSql("{0}", val2)); + } + + @Override + public MyLambdaQueryWrapper notBetween(boolean condition, String alias, MySFunction column, Object val1, Object val2) { + return doIt(condition, () -> getColumn(column, alias), NOT_BETWEEN, () -> formatSql("{0}", val1), AND, + () -> formatSql("{0}", val2)); + } + + @Override + public MyLambdaQueryWrapper like(boolean condition, String alias, MySFunction column, Object val) { + return likeValue(condition, LIKE, getColumn(column, alias), val, SqlLike.DEFAULT); + } + + @Override + public MyLambdaQueryWrapper notLike(boolean condition, String alias, MySFunction column, Object val) { + return likeValue(condition, NOT_LIKE, getColumn(column, alias), val, SqlLike.DEFAULT); + } + + @Override + public MyLambdaQueryWrapper likeLeft(boolean condition, String alias, MySFunction column, Object val) { + return likeValue(condition, LIKE, getColumn(column, alias), val, SqlLike.LEFT); + } + + @Override + public MyLambdaQueryWrapper likeRight(boolean condition, String alias, MySFunction column, Object val) { + return likeValue(condition, LIKE, getColumn(column, alias), val, SqlLike.RIGHT); + } + + @Override + public MyLambdaQueryWrapper and(boolean condition, Consumer> consumer) { + return and(condition).addNestedCondition(condition, consumer); + } + + @Override + public MyLambdaQueryWrapper or(boolean condition, Consumer> consumer) { + return or(condition).addNestedCondition(condition, consumer); + } + + @Override + public MyLambdaQueryWrapper nested(boolean condition, Consumer> consumer) { + return addNestedCondition(condition, consumer); + } + + @Override + public MyLambdaQueryWrapper not(boolean condition, Consumer> consumer) { + return not(condition).addNestedCondition(condition, consumer); + } + + + private MyLambdaQueryWrapper and(boolean condition) { + return doIt(condition, AND); + } + + private MyLambdaQueryWrapper or(boolean condition) { + return doIt(condition, OR); + } + + private MyLambdaQueryWrapper not(boolean condition) { + return doIt(condition, NOT); + } + + private MyLambdaQueryWrapper doIt(boolean condition, ISqlSegment... sqlSegments) { + if (condition) { + expression.add(sqlSegments); + } + return this; + } + + private MyLambdaQueryWrapper likeValue(boolean condition, SqlKeyword keyword, String column, Object val, SqlLike sqlLike) { + return doIt(condition, () -> column, keyword, () -> formatSql("{0}", SqlUtils.concatLike(val, sqlLike))); + } + + protected MyLambdaQueryWrapper addCondition(boolean condition, String column, SqlKeyword sqlKeyword, Object val) { + return doIt(condition, () -> column, sqlKeyword, () -> formatSql("{0}", val)); + } + + private MyLambdaQueryWrapper addNestedCondition(boolean condition, Consumer> consumer) { + if (condition) { + final MyLambdaQueryWrapper instance = instance(); + consumer.accept(instance); + return doIt(true, APPLY, instance); + } + return this; + } + + private ISqlSegment inExpression(Collection value) { + return () -> value.stream().map(i -> formatSql("{0}", i)) + .collect(joining(StringPool.COMMA, StringPool.LEFT_BRACKET, StringPool.RIGHT_BRACKET)); + } + + @Override + public MyLambdaQueryWrapper isNull(boolean condition, String alias, MySFunction column) { + return doIt(condition, () -> getColumn(column, alias), IS_NULL); + } + + @Override + public MyLambdaQueryWrapper isNotNull(boolean condition, String alias, MySFunction column) { + return doIt(condition, () -> getColumn(column, alias), IS_NOT_NULL); + } + + @Override + public MyLambdaQueryWrapper in(boolean condition, String alias, MySFunction column, Collection coll) { + return doIt(condition, () -> getColumn(column, alias), IN, inExpression(coll)); + } + + @Override + public MyLambdaQueryWrapper notIn(boolean condition, String alias, MySFunction column, Collection coll) { + return doIt(condition, () -> getColumn(column, alias), NOT_IN, inExpression(coll)); + } + + @Override + public MyLambdaQueryWrapper inSql(boolean condition, String alias, MySFunction column, String inValue) { + return doIt(condition, () -> getColumn(column, alias), IN, () -> String.format("(%s)", inValue)); + } + + @Override + public MyLambdaQueryWrapper notInSql(boolean condition, String alias, MySFunction column, String inValue) { + return doIt(condition, () -> getColumn(column, alias), NOT_IN, () -> String.format("(%s)", inValue)); + } + + @Override + public MyLambdaQueryWrapper groupBy(boolean condition, String alias, MySFunction... columns) { + if (ArrayUtils.isEmpty(columns)) { + return this; + } + return doIt(condition, GROUP_BY, + () -> columns.length == 1 ? getColumn(columns[0], alias) : getColumn(alias, columns)); + } + + @Override + public MyLambdaQueryWrapper orderBy(boolean condition, String alias, boolean isAsc, MySFunction... columns) { + if (ArrayUtils.isEmpty(columns)) { + return this; + } + SqlKeyword mode = isAsc ? ASC : DESC; + for (MySFunction column : columns) { + doIt(condition, ORDER_BY, () -> getColumn(column, alias), mode); + } + return this; + } + + @Override + public MyLambdaQueryWrapper having(boolean condition, String alias, String sqlHaving, Object... params) { + return doIt(condition, HAVING, () -> formatSqlIfNeed(condition, sqlHaving, params)); + } + + @Override + public MyLambdaQueryWrapper func(boolean condition, String alias, Consumer> consumer) { + if (condition) { + consumer.accept(this); + } + return this; + } +} diff --git a/src/main/java/com/example/mp/mybatis/plus/wrapper/SelectFunc.java b/src/main/java/com/example/mp/mybatis/plus/wrapper/SelectFunc.java new file mode 100644 index 0000000..378d467 --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/wrapper/SelectFunc.java @@ -0,0 +1,27 @@ +package com.example.mp.mybatis.plus.wrapper; + +public enum SelectFunc { + + SUM("SUM( %s )", "求和"), + COUNT("COUNT( %s )", "数量"), + AVG("AVG( %s )", "平均值"), + MAX("MAX( %s )", "最大值"), + MIN("MIN( %s )", "最小值"), + DATE_FORMAT("DATE_FORMAT( %s ,'%Y-%m-%d %H:%i:%s')", "日期格式化"); + + private final String sql; + private final String desc; + + SelectFunc(String sql, String desc) { + this.sql = sql; + this.desc = desc; + } + + public String getSql() { + return sql; + } + + public String getDesc() { + return desc; + } +} diff --git a/src/main/java/com/example/mp/mybatis/plus/wrapper/interfaces/MyCompare.java b/src/main/java/com/example/mp/mybatis/plus/wrapper/interfaces/MyCompare.java new file mode 100644 index 0000000..10c26fd --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/wrapper/interfaces/MyCompare.java @@ -0,0 +1,423 @@ +package com.example.mp.mybatis.plus.wrapper.interfaces; + +import com.example.mp.mybatis.plus.base.MyBaseEntity; +import com.example.mp.mybatis.plus.func.MySFunction; + +import java.io.Serializable; + +/** + * copy {@link com.baomidou.mybatisplus.core.conditions.interfaces.Compare} + */ +public interface MyCompare extends Serializable { + + /* 遗弃allEq */ + + /* ***************************************** eq start ********************************************* */ + + Children eq(boolean condition, String alias, MySFunction column, Object val); + + default Children eq(boolean condition, MySFunction column, Object val) { + return eq(condition, null, column, val); + } + + default Children eq(String alias, MySFunction column, Object val) { + return eq(true, alias, column, val); + } + + default Children eq(MySFunction column, Object val) { + return eq(true, null, column, val); + } + + Children eq(boolean condition, String alias, MySFunction column, String as, MySFunction val); + + default Children eq(MySFunction column, MySFunction val) { + return eq(true, null, column, null, val); + } + + default Children eq(Boolean condition, MySFunction column, MySFunction val) { + return eq(condition, null, column, null, val); + } + + default Children eq(String alias, MySFunction column, MySFunction val) { + return eq(true, alias, column, null, val); + } + + default Children eq(MySFunction column, String as, MySFunction val) { + return eq(true, null, column, as, val); + } + + default Children eq(Boolean condition, String alias, MySFunction column, MySFunction val) { + return eq(condition, alias, column, null, val); + } + + default Children eq(Boolean condition, MySFunction column, String as, MySFunction val) { + return eq(condition, null, column, as, val); + } + + default Children eq(String alias, MySFunction column, String as, MySFunction val) { + return eq(true, alias, column, as, val); + } + + /* ***************************************** eq end ********************************************* */ + + + /* ***************************************** ne start ********************************************* */ + + default Children ne(MySFunction column, Object val) { + return ne(true, null, column, val); + } + + default Children ne(boolean condition, MySFunction column, Object val) { + return ne(condition, null, column, val); + } + + default Children ne(String alias, MySFunction column, Object val) { + return ne(true, alias, column, val); + } + + Children ne(boolean condition, String alias, MySFunction column, Object val); + + default Children ne(MySFunction column, MySFunction val) { + return ne(true, null, column, null, val); + } + + default Children ne(boolean condition, MySFunction column, MySFunction val) { + return ne(condition, null, column, null, val); + } + + default Children ne(String alias, MySFunction column, MySFunction val) { + return ne(true, alias, column, null, val); + } + + default Children ne(MySFunction column, String as, MySFunction val) { + return ne(true, null, column, as, val); + } + + default Children ne(boolean condition, String alias, MySFunction column, MySFunction val) { + return ne(condition, alias, column, null, val); + } + + default Children ne(String alias, MySFunction column, String as, MySFunction val) { + return ne(true, alias, column, as, val); + } + + default Children ne(boolean condition, MySFunction column, String as, MySFunction val) { + return ne(condition, null, column, as, val); + } + + Children ne(boolean condition, String alias, MySFunction column, String as, MySFunction val); + + /* ***************************************** ne end ********************************************* */ + + + /* ***************************************** gt start ********************************************* */ + + default Children gt(MySFunction column, Object val) { + return gt(true, null, column, val); + } + + default Children gt(boolean condition, MySFunction column, Object val) { + return gt(condition, null, column, val); + } + + default Children gt(String alias, MySFunction column, Object val) { + return gt(true, alias, column, val); + } + + Children gt(boolean condition, String alias, MySFunction column, Object val); + + default Children gt(MySFunction column, MySFunction val) { + return gt(true, null, column, null, val); + } + + default Children gt(boolean condition, MySFunction column, MySFunction val) { + return gt(condition, null, column, null, val); + } + + default Children gt(String alias, MySFunction column, MySFunction val) { + return gt(true, alias, column, null, val); + } + + default Children gt(MySFunction column, String as, MySFunction val) { + return gt(true, null, column, as, val); + } + + default Children gt(boolean condition, String alias, MySFunction column, MySFunction val) { + return gt(condition, alias, column, null, val); + } + + default Children gt(String alias, MySFunction column, String as, MySFunction val) { + return gt(true, alias, column, as, val); + } + + default Children gt(boolean condition, MySFunction column, String as, MySFunction val) { + return gt(condition, null, column, as, val); + } + + Children gt(boolean condition, String alias, MySFunction column, String as, MySFunction val); + + + /* ***************************************** gt end ********************************************* */ + + + /* ***************************************** ge start ********************************************* */ + + default Children ge(MySFunction column, Object val) { + return ge(true, null, column, val); + } + + default Children ge(boolean condition, MySFunction column, Object val) { + return ge(condition, null, column, val); + } + + default Children ge(String alias, MySFunction column, Object val) { + return ge(true, alias, column, val); + } + + Children ge(boolean condition, String alias, MySFunction column, Object val); + + default Children ge(MySFunction column, MySFunction val) { + return ge(true, null, column, null, val); + } + + default Children ge(boolean condition, MySFunction column, MySFunction val) { + return ge(condition, null, column, null, val); + } + + default Children ge(String alias, MySFunction column, MySFunction val) { + return ge(true, alias, column, null, val); + } + + default Children ge(MySFunction column, String as, MySFunction val) { + return ge(true, null, column, as, val); + } + + default Children ge(boolean condition, String alias, MySFunction column, MySFunction val) { + return ge(condition, alias, column, null, val); + } + + default Children ge(String alias, MySFunction column, String as, MySFunction val) { + return ge(true, alias, column, as, val); + } + + default Children ge(boolean condition, MySFunction column, String as, MySFunction val) { + return ge(condition, null, column, as, val); + } + + Children ge(boolean condition, String alias, MySFunction column, String as, MySFunction val); + + /* ***************************************** ge end ********************************************* */ + + + /* ***************************************** lt start ********************************************* */ + + default Children lt(MySFunction column, Object val) { + return lt(true, null, column, val); + } + + default Children lt(boolean condition, MySFunction column, Object val) { + return lt(condition, null, column, val); + } + + default Children lt(String alias, MySFunction column, Object val) { + return lt(true, alias, column, val); + } + + Children lt(boolean condition, String alias, MySFunction column, Object val); + + default Children lt(MySFunction column, MySFunction val) { + return lt(true, null, column, null, val); + } + + default Children lt(boolean condition, MySFunction column, MySFunction val) { + return lt(condition, null, column, null, val); + } + + default Children lt(String alias, MySFunction column, MySFunction val) { + return lt(true, alias, column, null, val); + } + + default Children lt(MySFunction column, String as, MySFunction val) { + return lt(true, null, column, as, val); + } + + default Children lt(boolean condition, String alias, MySFunction column, MySFunction val) { + return lt(condition, alias, column, null, val); + } + + default Children lt(String alias, MySFunction column, String as, MySFunction val) { + return lt(true, alias, column, as, val); + } + + default Children lt(boolean condition, MySFunction column, String as, MySFunction val) { + return lt(condition, null, column, as, val); + } + + Children lt(boolean condition, String alias, MySFunction column, String as, MySFunction val); + + /* ***************************************** lt end ********************************************* */ + + + /* ***************************************** lt start ********************************************* */ + + default Children le(MySFunction column, Object val) { + return le(true, null, column, val); + } + + default Children le(boolean condition, MySFunction column, Object val) { + return le(condition, null, column, val); + } + + default Children le(String alias, MySFunction column, Object val) { + return le(true, alias, column, val); + } + + Children le(boolean condition, String alias, MySFunction column, Object val); + + default Children le(MySFunction column, MySFunction val) { + return le(true, null, column, null, val); + } + + default Children le(boolean condition, MySFunction column, MySFunction val) { + return le(condition, null, column, null, val); + } + + default Children le(String alias, MySFunction column, MySFunction val) { + return le(true, alias, column, null, val); + } + + default Children le(MySFunction column, String as, MySFunction val) { + return le(true, null, column, as, val); + } + + default Children le(boolean condition, String alias, MySFunction column, MySFunction val) { + return le(condition, alias, column, null, val); + } + + default Children le(String alias, MySFunction column, String as, MySFunction val) { + return le(true, alias, column, as, val); + } + + default Children le(boolean condition, MySFunction column, String as, MySFunction val) { + return le(condition, null, column, as, val); + } + + Children le(boolean condition, String alias, MySFunction column, String as, MySFunction val); + + /* ***************************************** le end ********************************************* */ + + /* ***************************************** between start ********************************************* */ + + default Children between(MySFunction column, Object val1, Object val2) { + return between(true, null, column, val1, val2); + } + + default Children between(boolean condition, MySFunction column, Object val1, Object val2) { + return between(condition, null, column, val1, val2); + } + + default Children between(String alias, MySFunction column, Object val1, Object val2) { + return between(true, alias, column, val1, val2); + } + + Children between(boolean condition, String alias, MySFunction column, Object val1, Object val2); + + /* ***************************************** between end ********************************************* */ + + + /* ***************************************** notBetween start ********************************************* */ + + default Children notBetween(MySFunction column, Object val1, Object val2) { + return notBetween(true, null, column, val1, val2); + } + + default Children notBetween(boolean condition, MySFunction column, Object val1, Object val2) { + return notBetween(condition, null, column, val1, val2); + } + + default Children notBetween(String alias, MySFunction column, Object val1, Object val2) { + return notBetween(true, alias, column, val1, val2); + } + + Children notBetween(boolean condition, String alias, MySFunction column, Object val1, Object val2); + + /* ***************************************** notBetween end ********************************************* */ + + + /* ***************************************** like start ********************************************* */ + + default Children like(MySFunction column, Object val) { + return like(true, null, column, val); + } + + default Children like(boolean condition, MySFunction column, Object val) { + return like(condition, null, column, val); + } + + default Children like(String alias, MySFunction column, Object val) { + return like(true, alias, column, val); + } + + Children like(boolean condition, String alias, MySFunction column, Object val); + + /* ***************************************** like end ********************************************* */ + + + /* ***************************************** notLike start ********************************************* */ + + default Children notLike(MySFunction column, Object val) { + return notLike(true, null, column, val); + } + + default Children notLike(boolean condition, MySFunction column, Object val) { + return notLike(condition, null, column, val); + } + + default Children notLike(String alias, MySFunction column, Object val) { + return notLike(true, alias, column, val); + } + + Children notLike(boolean condition, String alias, MySFunction column, Object val); + + /* ***************************************** notLike end ********************************************* */ + + + /* ***************************************** likeLeft start ********************************************* */ + + default Children likeLeft(MySFunction column, Object val) { + return likeLeft(true, null, column, val); + } + + default Children likeLeft(boolean condition, MySFunction column, Object val) { + return likeLeft(condition, null, column, val); + } + + default Children likeLeft(String alias, MySFunction column, Object val) { + return likeLeft(true, alias, column, val); + } + + Children likeLeft(boolean condition, String alias, MySFunction column, Object val); + + /* ***************************************** likeLeft end ********************************************* */ + + + + /* ***************************************** likeRight start ********************************************* */ + + default Children likeRight(MySFunction column, Object val) { + return likeRight(true, null, column, val); + } + + default Children likeRight(boolean condition, MySFunction column, Object val) { + return likeRight(condition, null, column, val); + } + + default Children likeRight(String alias, MySFunction column, Object val) { + return likeRight(true, alias, column, val); + } + + Children likeRight(boolean condition, String alias, MySFunction column, Object val); + + /* ***************************************** likeRight end ********************************************* */ + +} diff --git a/src/main/java/com/example/mp/mybatis/plus/wrapper/interfaces/MyFunc.java b/src/main/java/com/example/mp/mybatis/plus/wrapper/interfaces/MyFunc.java new file mode 100644 index 0000000..625f73a --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/wrapper/interfaces/MyFunc.java @@ -0,0 +1,214 @@ +package com.example.mp.mybatis.plus.wrapper.interfaces; + +import com.example.mp.mybatis.plus.base.MyBaseEntity; +import com.example.mp.mybatis.plus.func.MySFunction; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Collection; +import java.util.Optional; +import java.util.function.Consumer; + +import static java.util.stream.Collectors.toList; + +/** + * copy {@link com.baomidou.mybatisplus.core.conditions.interfaces.Func} + */ +@SuppressWarnings("unchecked") +public interface MyFunc extends Serializable { + + default Children isNull(MySFunction column) { + return isNull(true, null, column); + } + + default Children isNull(boolean condition, MySFunction column) { + return isNull(condition, null, column); + } + + default Children isNull(String alias, MySFunction column) { + return isNull(true, alias, column); + } + + Children isNull(boolean condition, String alias, MySFunction column); + + + default Children isNotNull(MySFunction column) { + return isNotNull(true, column); + } + + default Children isNotNull(boolean condition, MySFunction column) { + return isNotNull(condition, null, column); + } + + default Children isNotNull(String alias, MySFunction column) { + return isNotNull(true, alias, column); + } + + Children isNotNull(boolean condition, String alias, MySFunction column); + + default Children in(MySFunction column, Collection coll) { + return in(true, null, column, coll); + } + + default Children in(boolean condition, MySFunction column, Collection coll) { + return in(condition, null, column, coll); + } + + default Children in(String alias, MySFunction column, Collection coll) { + return in(true, alias, column, coll); + } + + Children in(boolean condition, String alias, MySFunction column, Collection coll); + + default Children in(MySFunction column, Object... values) { + return in(true, null, column, values); + } + + default Children in(boolean condition, MySFunction column, Object... values) { + return in(condition, null, column, values); + } + + default Children in(String alias, MySFunction column, Object... values) { + return in(true, alias, column, values); + } + + default Children in(boolean condition, String alias, MySFunction column, Object... values) { + return in(condition, alias, column, Arrays.stream(Optional.ofNullable(values).orElseGet(() -> new Object[]{})) + .collect(toList())); + } + + default Children notIn(MySFunction column, Collection coll) { + return notIn(true, null, column, coll); + } + + default Children notIn(boolean condition, MySFunction column, Collection coll) { + return notIn(condition, null, column, coll); + } + + default Children notIn(String alias, MySFunction column, Collection coll) { + return notIn(true, alias, column, coll); + } + + Children notIn(boolean condition, String alias, MySFunction column, Collection coll); + + default Children notIn(MySFunction column, Object... value) { + return notIn(true, null, column, value); + } + + default Children notIn(boolean condition, MySFunction column, Object... value) { + return notIn(condition, null, column, value); + } + + default Children notIn(String alias, MySFunction column, Object... value) { + return notIn(true, alias, column, value); + } + + default Children notIn(boolean condition, String alias, MySFunction column, Object... values) { + return notIn(condition, alias, column, Arrays.stream(Optional.ofNullable(values).orElseGet(() -> new Object[]{})) + .collect(toList())); + } + + default Children inSql(MySFunction column, String inValue) { + return inSql(true, null, column, inValue); + } + + default Children inSql(boolean condition, MySFunction column, String inValue) { + return inSql(condition, null, column, inValue); + } + + default Children inSql(String alias, MySFunction column, String inValue) { + return inSql(true, alias, column, inValue); + } + + Children inSql(boolean condition, String alias, MySFunction column, String inValue); + + default Children notInSql(MySFunction column, String inValue) { + return notInSql(true, null, column, inValue); + } + + default Children notInSql(boolean condition, MySFunction column, String inValue) { + return notInSql(condition, null, column, inValue); + } + + default Children notInSql(String alias, MySFunction column, String inValue) { + return notInSql(true, alias, column, inValue); + } + + Children notInSql(boolean condition, String alias, MySFunction column, String inValue); + + default Children groupBy(MySFunction... columns) { + return groupBy(true, null, columns); + } + + default Children groupBy(boolean condition, MySFunction... columns) { + return groupBy(condition, null, columns); + } + + default Children groupBy(String alias, MySFunction... columns) { + return groupBy(true, alias, columns); + } + + Children groupBy(boolean condition, String alias, MySFunction... columns); + + default Children orderByAsc(MySFunction... columns) { + return orderByAsc(true, null, columns); + } + + default Children orderByAsc(boolean condition, MySFunction... columns) { + return orderByAsc(condition, null, columns); + } + + default Children orderByAsc(String alias, MySFunction... columns) { + return orderByAsc(true, alias, columns); + } + + default Children orderByAsc(boolean condition, String alias, MySFunction... columns) { + return orderBy(condition, alias, true, columns); + } + + default Children orderByDesc(MySFunction... columns) { + return orderByDesc(true, null, columns); + } + + default Children orderByDesc(boolean condition, MySFunction... columns) { + return orderByDesc(condition, null, columns); + } + + default Children orderByDesc(String alias, MySFunction... columns) { + return orderByDesc(true, alias, columns); + } + + default Children orderByDesc(boolean condition, String alias, MySFunction... columns) { + return orderBy(condition, alias, false, columns); + } + + Children orderBy(boolean condition, String alias, boolean isAsc, MySFunction... columns); + + default Children having(String sqlHaving, Object... params) { + return having(true, null, sqlHaving, params); + } + + default Children having(boolean condition, String sqlHaving, Object... params) { + return having(condition, null, sqlHaving, params); + } + + default Children having(String alias, String sqlHaving, Object... params) { + return having(true, alias, sqlHaving, params); + } + + Children having(boolean condition, String alias, String sqlHaving, Object... params); + + default Children func(Consumer consumer) { + return func(true, null, consumer); + } + + default Children func(boolean condition, Consumer consumer) { + return func(condition, null, consumer); + } + + default Children func(String alias, Consumer consumer) { + return func(true, alias, consumer); + } + + Children func(boolean condition, String alias, Consumer consumer); +} diff --git a/src/main/java/com/example/mp/mybatis/plus/wrapper/interfaces/MyJoin.java b/src/main/java/com/example/mp/mybatis/plus/wrapper/interfaces/MyJoin.java new file mode 100644 index 0000000..742b09f --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/wrapper/interfaces/MyJoin.java @@ -0,0 +1,90 @@ +package com.example.mp.mybatis.plus.wrapper.interfaces; + +import com.example.mp.mybatis.plus.base.MyBaseEntity; +import com.example.mp.mybatis.plus.func.MySFunction; +import com.example.mp.mybatis.plus.wrapper.MyJoinLambdaQueryWrapper; + +import java.util.function.Function; + +/** + * @author yulichang + */ +public interface MyJoin { + + + Children leftJoin(boolean condition, + String alias, + MySFunction leftCondition, + MySFunction rightCondition, + Function, MyJoinLambdaQueryWrapper> rightWrapper); + + + default Children leftJoin(MySFunction leftCondition, + MySFunction rightCondition, + Function, MyJoinLambdaQueryWrapper> rightWrapper) { + return leftJoin(true, null, leftCondition, rightCondition, rightWrapper); + } + + default Children leftJoin(String alias, MySFunction leftCondition, MySFunction rightCondition, Function, MyJoinLambdaQueryWrapper> rightWrapper) { + return leftJoin(true, alias, leftCondition, rightCondition, rightWrapper); + } + + default Children leftJoin(boolean condition, + MySFunction leftCondition, + MySFunction rightCondition, + Function, MyJoinLambdaQueryWrapper> rightWrapper) { + return leftJoin(condition, null, leftCondition, rightCondition, rightWrapper); + } + + + Children rightJoin(boolean condition, + String alias, + MySFunction leftCondition, + MySFunction rightCondition, + Function, MyJoinLambdaQueryWrapper> rightWrapper); + + + default Children rightJoin(MySFunction leftCondition, + MySFunction rightCondition, + Function, MyJoinLambdaQueryWrapper> rightWrapper) { + return rightJoin(true, null, leftCondition, rightCondition, rightWrapper); + } + + default Children rightJoin(String alias, MySFunction leftCondition, MySFunction rightCondition, Function, MyJoinLambdaQueryWrapper> rightWrapper) { + return rightJoin(true, alias, leftCondition, rightCondition, rightWrapper); + } + + default Children rightJoin(boolean condition, + MySFunction leftCondition, + MySFunction rightCondition, + Function, MyJoinLambdaQueryWrapper> rightWrapper) { + return rightJoin(condition, null, leftCondition, rightCondition, rightWrapper); + } + + + Children innerJoin(boolean condition, + String alias, + MySFunction leftCondition, + MySFunction rightCondition, + Function, MyJoinLambdaQueryWrapper> rightWrapper); + + + default Children innerJoin(MySFunction leftCondition, + MySFunction rightCondition, + Function, MyJoinLambdaQueryWrapper> rightWrapper) { + return innerJoin(true, null, leftCondition, rightCondition, rightWrapper); + } + + default Children innerJoin(String alias, MySFunction leftCondition, MySFunction rightCondition, Function, MyJoinLambdaQueryWrapper> rightWrapper) { + return innerJoin(true, alias, leftCondition, rightCondition, rightWrapper); + } + + default Children innerJoin(boolean condition, + MySFunction leftCondition, + MySFunction rightCondition, + Function, MyJoinLambdaQueryWrapper> rightWrapper) { + return innerJoin(condition, null, leftCondition, rightCondition, rightWrapper); + } + + +} diff --git a/src/main/java/com/example/mp/mybatis/plus/wrapper/interfaces/MyMPJoin.java b/src/main/java/com/example/mp/mybatis/plus/wrapper/interfaces/MyMPJoin.java new file mode 100644 index 0000000..6c7c32a --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/wrapper/interfaces/MyMPJoin.java @@ -0,0 +1,130 @@ +package com.example.mp.mybatis.plus.wrapper.interfaces; + +import java.io.Serializable; + +/** + * copy {@link com.baomidou.mybatisplus.core.conditions.interfaces.Join} + */ +public interface MyMPJoin extends Serializable { + + /** + * ignore + */ + default Children or() { + return or(true); + } + + /** + * 拼接 OR + * + * @param condition 执行条件 + * @return children + */ + Children or(boolean condition); + + /** + * ignore + */ + default Children apply(String applySql, Object... value) { + return apply(true, applySql, value); + } + + /** + * 拼接 sql + *

!! 会有 sql 注入风险 !!

+ *

例1: apply("id = 1")

+ *

例2: apply("date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")

+ *

例3: apply("date_format(dateColumn,'%Y-%m-%d') = {0}", LocalDate.now())

+ * + * @param condition 执行条件 + * @return children + */ + Children apply(boolean condition, String applySql, Object... value); + + /** + * ignore + */ + default Children last(String lastSql) { + return last(true, lastSql); + } + + /** + * 无视优化规则直接拼接到 sql 的最后(有sql注入的风险,请谨慎使用) + *

例: last("limit 1")

+ *

注意只能调用一次,多次调用以最后一次为准

+ * + * @param condition 执行条件 + * @param lastSql sql语句 + * @return children + */ + Children last(boolean condition, String lastSql); + + /** + * ignore + */ + default Children comment(String comment) { + return comment(true, comment); + } + + /** + * sql 注释(会拼接在 sql 的最后面) + * + * @param condition 执行条件 + * @param comment sql注释 + * @return children + */ + Children comment(boolean condition, String comment); + + /** + * ignore + */ + default Children first(String firstSql) { + return first(true, firstSql); + } + + /** + * sql 起始句(会拼接在SQL语句的起始处) + * + * @param condition 执行条件 + * @param firstSql 起始语句 + * @return children + * @since 3.3.1 + */ + Children first(boolean condition, String firstSql); + + /** + * ignore + */ + default Children exists(String existsSql) { + return exists(true, existsSql); + } + + /** + * 拼接 EXISTS ( sql语句 ) + *

!! sql 注入方法 !!

+ *

例: exists("select id from table where age = 1")

+ * + * @param condition 执行条件 + * @param existsSql sql语句 + * @return children + */ + Children exists(boolean condition, String existsSql); + + /** + * ignore + */ + default Children notExists(String existsSql) { + return notExists(true, existsSql); + } + + /** + * 拼接 NOT EXISTS ( sql语句 ) + *

!! sql 注入方法 !!

+ *

例: notExists("select id from table where age = 1")

+ * + * @param condition 执行条件 + * @param existsSql sql语句 + * @return children + */ + Children notExists(boolean condition, String existsSql); +} diff --git a/src/main/java/com/example/mp/mybatis/plus/wrapper/interfaces/MyNested.java b/src/main/java/com/example/mp/mybatis/plus/wrapper/interfaces/MyNested.java new file mode 100644 index 0000000..a829bd8 --- /dev/null +++ b/src/main/java/com/example/mp/mybatis/plus/wrapper/interfaces/MyNested.java @@ -0,0 +1,87 @@ +package com.example.mp.mybatis.plus.wrapper.interfaces; + +import java.io.Serializable; +import java.util.function.Consumer; + +/** + * copy {@link com.baomidou.mybatisplus.core.conditions.interfaces.Nested} + */ +public interface MyNested extends Serializable { + + /** + * ignore + */ + default Children and(Consumer consumer) { + return and(true, consumer); + } + + /** + * AND 嵌套 + *

+ * 例: and(i -> i.eq("name", "李白").ne("status", "活着")) + *

+ * + * @param condition 执行条件 + * @param consumer 消费函数 + * @return children + */ + Children and(boolean condition, Consumer consumer); + + + /** + * ignore + */ + default Children or(Consumer consumer) { + return or(true, consumer); + } + + /** + * OR 嵌套 + *

+ * 例: or(i -> i.eq("name", "李白").ne("status", "活着")) + *

+ * + * @param condition 执行条件 + * @param consumer 消费函数 + * @return children + */ + Children or(boolean condition, Consumer consumer); + + /** + * ignore + */ + default Children nested(Consumer consumer) { + return nested(true, consumer); + } + + /** + * 正常嵌套 不带 AND 或者 OR + *

+ * 例: nested(i -> i.eq("name", "李白").ne("status", "活着")) + *

+ * + * @param condition 执行条件 + * @param consumer 消费函数 + * @return children + */ + Children nested(boolean condition, Consumer consumer); + + /** + * ignore + */ + default Children not(Consumer consumer) { + return not(true, consumer); + } + + /** + * not嵌套 + *

+ * 例: not(i -> i.eq("name", "李白").ne("status", "活着")) + *

+ * + * @param condition 执行条件 + * @param consumer 消费函数 + * @return children + */ + Children not(boolean condition, Consumer consumer); +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..34eb502 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,14 @@ +spring: + datasource: + type: com.alibaba.druid.pool.DruidDataSource + druid: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/mp-test?useSSL=false&serverTimezone=Asia/Shanghai + username: root + password: 123456 + +mybatis-plus: + global-config: + banner: false + configuration: + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl \ No newline at end of file diff --git a/src/test/java/com/example/mp/MpJoinTest.java b/src/test/java/com/example/mp/MpJoinTest.java new file mode 100644 index 0000000..1021a17 --- /dev/null +++ b/src/test/java/com/example/mp/MpJoinTest.java @@ -0,0 +1,135 @@ +package com.example.mp; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.example.mp.business.dto.UserDTO; +import com.example.mp.business.entity.UserAddressEntity; +import com.example.mp.business.entity.UserEntity; +import com.example.mp.business.mapper.UserMapper; +import com.example.mp.business.service.UserService; +import com.example.mp.mybatis.plus.wrapper.MyLambdaQueryWrapper; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 连表 + */ +@SpringBootTest +class MpJoinTest { + + @Resource + private UserService userService; + + @Resource + private UserMapper userMapper; + + /** + * 快速开始 + * 简单的连表查询 + */ + @Test + void quickStart() { + //简单的连表查询 --> user left join user_address + //mapper + List dtoList1 = userMapper.selectJoinList(new MyLambdaQueryWrapper() + .selectAll(UserEntity.class)//查询全部字段,mp中默认全部字段,但是这默认为空,class按道理可以不传,从泛型中获取,目前还没有想到解决方案 + .leftJoin(UserEntity::getId, UserAddressEntity::getUserId,// left join -> sql中join后面on的两个比骄傲字段 + right -> right.selectAll(UserAddressEntity.class)), + UserDTO.class); + log(dtoList1.get(0).getTel()); + + //service实现 + List dtoList2 = userService.selectJoinList(new MyLambdaQueryWrapper() + .selectAll(UserEntity.class) + //同样支持条件判断 false不会进行连表 right join(还有 inner join) -> sql中join后面on的两个比较字段 + .rightJoin(true, UserEntity::getId, UserAddressEntity::getUserId, + right -> right.selectAll(UserAddressEntity.class)), + UserDTO.class); + log(dtoList2.get(0).getHeadImg()); + } + + /** + * 别名用法(as) + * 简单的连表查询 + */ + @Test + void test1() { + //连表查询 --> user left join user_address + //mapper + List dtoList1 = userMapper.selectJoinList(new MyLambdaQueryWrapper() + .selectAll(UserEntity.class) + .as(UserEntity::getId, UserDTO::getId)//sql as 当数据库字段与属性不匹配是使用, user.id as UserDTO.id + .leftJoin(UserEntity::getId, UserAddressEntity::getUserId, right -> right + .asSum(UserAddressEntity::getAddress, UserDTO::getAddress)//as 的拓展 sum() 还有 count avg max min 等... + .selectAll(UserAddressEntity.class)), + UserDTO.class); + log(dtoList1.get(0).getTel()); + //service 略... + } + + /** + * 待条件的连表查询 + */ + @Test + void test2() { + //连表查询 --> user left join user_address + //mapper + List dtoList1 = userMapper.selectJoinList(new MyLambdaQueryWrapper() + .selectAll(UserEntity.class) + .leftJoin(UserEntity::getId, UserAddressEntity::getUserId, right -> right + .selectAll(UserAddressEntity.class)) + .eq(true, UserEntity::getId, 1)//支持条件判断 + .like(UserAddressEntity::getTel, "1")//支持所有join的表字段 UserEntity 或 UserAddressEntity都可以 + .eq(UserEntity::getId, UserAddressEntity::getUserId)//甚至可以字段与字段比较 UserEntity.id = UserAddressEntity.id + /* 其他 .ne() .gt() .ge() .... 请参考 mybatis-plus */ + , UserDTO.class); + log(dtoList1.get(0).getTel()); + //service 略... + } + + /** + * 连表分页查询 (请配置mybatis-plus 分页插件) + */ + @Test + void test3() { + //连表查询 --> user left join user_address + //mapper + IPage page = userMapper.selectJoinPage(new Page<>(1, 10), new MyLambdaQueryWrapper() + .selectAll(UserEntity.class) + .leftJoin(UserEntity::getId, UserAddressEntity::getUserId, right -> right + .selectAll(UserAddressEntity.class)) + .eq(true, UserEntity::getId, 1)//支持条件判断 + .like(UserAddressEntity::getTel, "1")//支持所有join的表字段 UserEntity 或 UserAddressEntity都可以 + .eq(UserEntity::getId, UserAddressEntity::getUserId)//甚至可以字段与字段比较 UserEntity.id = UserAddressEntity.id + /* 其他 .ne() .gt() .ge() .... 请参考 mybatis-plus */ + , UserDTO.class); + log(page.getRecords().get(0).getTel()); + //service 略... + } + + + /** + * 自定义别名支持 + * 如果表重复(自连接,或join同一张表多次 需要用到别名) + *

+ * 不只是两张表,这个框架没有限制join数量,理论上可以无限join但不建议 [狗头] + *

+ * 自己去探索发现吧! + */ + @Test + void test4() { + //todo + } + + + private void log(String format, String... args) { + System.err.println(String.format(format, args)); + } + + private void log(String msg) { + System.err.println(msg); + } +}