From 866bccff286cd6967b2102a9972892cfcf1b0164 Mon Sep 17 00:00:00 2001 From: bjdys Date: Thu, 12 Aug 2021 09:28:32 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=80=E5=AF=B9=E4=B8=80=20=E4=B8=80?= =?UTF-8?q?=E5=AF=B9=E5=A4=9A=20=E5=85=B3=E7=B3=BB=E6=98=A0=E5=B0=84?= =?UTF-8?q?=E6=B3=A8=E8=A7=A3=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 5 +- .../core/metadata/MPJMappingWrapper.java | 86 +++++ .../core/metadata/MPJTableFieldInfo.java | 243 ++++++++++++++ .../core/metadata/MPJTableInfo.java | 38 +++ .../core/metadata/MPJTableInfoHelper.java | 117 +++++-- .../yulichang/annotation/MPJMapping.java | 88 +++++ .../yulichang/annotation/MPJMappingApply.java | 21 ++ .../annotation/MPJMappingCondition.java | 34 ++ .../yulichang/base/MPJBaseDeepService.java | 307 ++++++++++++++++++ .../yulichang/base/MPJBaseJoinService.java | 65 ++++ .../github/yulichang/base/MPJBaseMapper.java | 47 +++ .../github/yulichang/base/MPJBaseService.java | 50 +-- .../yulichang/base/MPJBaseServiceImpl.java | 66 +--- .../yulichang/injector/MPJSqlInjector.java | 36 +- .../yulichang/interceptor/MPJInterceptor.java | 9 +- .../yulichang/toolkit/SpringContentUtils.java | 25 ++ src/main/resources/META-INF/spring.factories | 3 +- 17 files changed, 1074 insertions(+), 166 deletions(-) create mode 100644 src/main/java/com/baomidou/mybatisplus/core/metadata/MPJMappingWrapper.java create mode 100644 src/main/java/com/baomidou/mybatisplus/core/metadata/MPJTableFieldInfo.java create mode 100644 src/main/java/com/baomidou/mybatisplus/core/metadata/MPJTableInfo.java create mode 100644 src/main/java/com/github/yulichang/annotation/MPJMapping.java create mode 100644 src/main/java/com/github/yulichang/annotation/MPJMappingApply.java create mode 100644 src/main/java/com/github/yulichang/annotation/MPJMappingCondition.java create mode 100644 src/main/java/com/github/yulichang/base/MPJBaseDeepService.java create mode 100644 src/main/java/com/github/yulichang/base/MPJBaseJoinService.java create mode 100644 src/main/java/com/github/yulichang/toolkit/SpringContentUtils.java diff --git a/pom.xml b/pom.xml index 0cdb9ad..86c0ff6 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.github.yulichang mybatis-plus-join - 1.1.8 + 1.1.9-SNAPSHOT mybatis-plus-join An enhanced toolkit of Mybatis-Plus to simplify development. https://github.com/yulichang/mybatis-plus-join @@ -32,6 +32,9 @@ UTF-8 1.8 1.8 + + 1.8 + 1.8 diff --git a/src/main/java/com/baomidou/mybatisplus/core/metadata/MPJMappingWrapper.java b/src/main/java/com/baomidou/mybatisplus/core/metadata/MPJMappingWrapper.java new file mode 100644 index 0000000..7a1bb20 --- /dev/null +++ b/src/main/java/com/baomidou/mybatisplus/core/metadata/MPJMappingWrapper.java @@ -0,0 +1,86 @@ +package com.baomidou.mybatisplus.core.metadata; + + +import com.baomidou.mybatisplus.core.enums.SqlKeyword; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.github.yulichang.annotation.MPJMapping; +import com.github.yulichang.annotation.MPJMappingApply; +import com.github.yulichang.annotation.MPJMappingCondition; +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +/** + * 关联查询条件 + * + * @author yulichang + * @since 1.2.0 + */ +@Data +public class MPJMappingWrapper { + + private final boolean hasFirst; + private String first; + + private final boolean hasSelect; + private String select; + + private final boolean hasApply; + private List applyList; + + private final boolean hasCondition; + private List conditionList; + + private final boolean hasLast; + private String last; + + public MPJMappingWrapper(MPJMapping mapping) { + this.hasFirst = StringUtils.isNotBlank(mapping.first()); + if (this.hasFirst) { + this.first = mapping.first(); + } + + this.hasSelect = StringUtils.isNotBlank(mapping.select()); + if (this.hasSelect) { + this.select = mapping.select(); + } + + this.hasApply = mapping.apply().length > 0; + if (this.hasApply) { + this.applyList = new ArrayList<>(); + for (MPJMappingApply apply : mapping.apply()) { + this.applyList.add(new Apply(apply.value(), apply.args())); + } + } + + this.hasCondition = mapping.condition().length > 0; + if (this.hasCondition) { + this.conditionList = new ArrayList<>(); + for (MPJMappingCondition condition : mapping.condition()) { + conditionList.add(new Condition(condition.keyWord(), condition.column(), condition.value())); + } + } + + this.hasLast = StringUtils.isNotBlank(mapping.last()); + if (this.hasLast) { + this.last = mapping.last(); + } + } + + @Data + @AllArgsConstructor + public static class Apply { + private String sql; + private String[] val; + } + + @Data + @AllArgsConstructor + public static class Condition { + private SqlKeyword keyword; + private String column; + private String[] val; + } +} diff --git a/src/main/java/com/baomidou/mybatisplus/core/metadata/MPJTableFieldInfo.java b/src/main/java/com/baomidou/mybatisplus/core/metadata/MPJTableFieldInfo.java new file mode 100644 index 0000000..42e3db6 --- /dev/null +++ b/src/main/java/com/baomidou/mybatisplus/core/metadata/MPJTableFieldInfo.java @@ -0,0 +1,243 @@ +package com.baomidou.mybatisplus.core.metadata; + +import com.baomidou.mybatisplus.core.toolkit.Assert; +import com.baomidou.mybatisplus.core.toolkit.ClassUtils; +import com.baomidou.mybatisplus.core.toolkit.ReflectionKit; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.github.yulichang.annotation.MPJMapping; +import com.github.yulichang.base.MPJBaseMapper; +import com.github.yulichang.exception.MPJException; +import com.github.yulichang.toolkit.SpringContentUtils; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.ToString; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * 字段属性 + * + * @author yulichang + * @see TableFieldInfo + * @since 1.2.0 + */ +@Getter +@ToString +@EqualsAndHashCode +public class MPJTableFieldInfo { + + /** + * 实体类 + */ + private final Class entityType; + /** + * 属性 + */ + private final Field field; + /** + * 属性 + */ + private final boolean fieldIsMap; + /** + * 属性是否是集合 + */ + private final boolean isCollection; + /** + * 当前映射属性 + */ + private Field thisField; + /** + * 当前类实体属性 + */ + private final String thisProperty; + /** + * 当前字段信息 + */ + private String thisColumn; + /** + * 当前字段信息 + */ + private String thisMapKey; + /** + * 映射实体类 + */ + private final Class joinClass; + /** + * 映射属性名 + */ + private final String joinProperty; + /** + * 映射属性数据库列名 + */ + private String joinColumn; + /** + * 映射属性字段 + */ + private Field joinField; + /** + * fieldIsMap 为true时使用 + * 映射查询Map 的key + * 默认为 关联字段的数据库列名 + */ + private String joinMapKey; + /** + * 关联的mapper引用 + */ + private MPJBaseMapper joinMapper; + /** + * 关联查询条件配置 + */ + private final MPJMappingWrapper wrapper; + + /** + * 初始化关联字段信息 + */ + public MPJTableFieldInfo(Class entityType, MPJMapping mapping, Field field) { + field.setAccessible(true); + this.entityType = entityType; + this.field = field; + this.joinClass = mapping.tag(); + this.isCollection = Collection.class.isAssignableFrom(field.getType()); + this.thisMapKey = StringUtils.isBlank(mapping.thisMapKey()) ? null : mapping.thisMapKey(); + this.joinMapKey = StringUtils.isBlank(mapping.joinMapKsy()) ? null : mapping.joinMapKsy(); + this.fieldIsMap = mapping.isMap();//TODO 应该可以自动检测 + this.wrapper = new MPJMappingWrapper(mapping); + if (this.isCollection && field.getType() != List.class && field.getType() != ArrayList.class) { + throw new MPJException("对多关系的数据结构目前只支持 暂不支持其他Collection实现 " + field.getType().getTypeName()); + } + if (StringUtils.isNotBlank(mapping.joinField())) { + this.joinProperty = mapping.joinField(); + } else { + TableInfo info = getTableInfo(this.joinClass); + Assert.isTrue(info.havePK(), "实体未定义主键 %s ", this.joinClass.getName()); + this.joinProperty = info.getKeyProperty(); + } + if (StringUtils.isNotBlank(mapping.thisField())) { + this.thisProperty = mapping.thisField(); + } else { + TableInfo info = getTableInfo(this.entityType); + Assert.isTrue(info.havePK(), "实体未定义主键 %s ", this.entityType.getName()); + this.thisProperty = info.getKeyProperty(); + } + } + + @SuppressWarnings("ConstantConditions") + public Field getThisField() { + if (this.thisField == null) { + TableInfo tableInfo = getTableInfo(this.entityType); + if (tableInfo.havePK() && this.thisProperty.equals(tableInfo.getKeyProperty())) { + this.thisField = ReflectionKit.getFieldList(ClassUtils.getUserClass(entityType)).stream().filter(f -> + f.getName().equals(tableInfo.getKeyProperty())).findFirst().orElse(null); + Assert.notNull(this.thisField, "MPJMapping注解thisField不存在 %s , %s", entityType.getName(), + StringUtils.isBlank(this.thisProperty) ? "主键" : this.thisProperty); + this.thisColumn = tableInfo.getKeyColumn(); + } else { + TableFieldInfo fieldInfo = tableInfo.getFieldList().stream().filter(f -> + f.getField().getName().equals(this.thisProperty)).findFirst().orElse(null); + Assert.notNull(fieldInfo, "MPJMapping注解thisField不存在 %s , %s", entityType.getName(), + StringUtils.isBlank(this.thisProperty) ? "主键" : this.thisProperty); + this.thisField = fieldInfo.getField(); + this.thisColumn = fieldInfo.getColumn(); + } + this.thisField.setAccessible(true); + } + return this.thisField; + } + + public String getJoinColumn() { + if (StringUtils.isBlank(this.joinColumn)) { + TableInfo joinTableInfo = getTableInfo(this.joinClass); + TableFieldInfo joinFieldInfo = joinTableInfo.getFieldList().stream().filter(f -> + f.getField().getName().equals(this.joinProperty)).findFirst().orElse(null); + if (joinFieldInfo == null) { + if (joinTableInfo.havePK() && this.joinProperty.equals(joinTableInfo.getKeyProperty())) { + this.joinColumn = joinTableInfo.getKeyColumn(); + this.joinField = ReflectionKit.getFieldList(this.joinClass).stream().filter(i -> + i.getName().equals(joinTableInfo.getKeyProperty())).findFirst().orElse(null); + } + } else { + this.joinColumn = joinFieldInfo.getColumn(); + this.joinField = joinFieldInfo.getField(); + } + Assert.notNull(this.joinField, "MPJMapping注解thisField不存在 %s , %s", this.joinClass.getName(), + StringUtils.isBlank(this.joinProperty) ? "主键" : this.joinProperty); + Assert.notNull(this.joinColumn, "MPJMapping注解thisField不存在 %s , %s", this.joinClass.getName(), + StringUtils.isBlank(this.joinProperty) ? "主键" : this.joinProperty); + this.joinField.setAccessible(true); + } + return this.joinColumn; + } + + public String getThisMapKey() { + if (this.thisMapKey == null) { + this.thisMapKey = getJoinColumn(); + } + return this.thisMapKey; + } + + public Field getJoinField() { + if (this.joinField == null) { + this.getJoinColumn(); + } + return this.joinField; + } + + + public String getJoinMapKey() { + if (this.joinMapKey == null) { + this.joinMapKey = getJoinColumn(); + } + return joinMapKey; + } + + public MPJBaseMapper getJoinMapper() { + if (this.joinMapper == null) { + MPJTableInfo joinTableInfo = MPJTableInfoHelper.getTableInfos().stream().filter(table -> + table.getTableInfo().getEntityType() == this.joinClass).findFirst().orElse(null); + if (joinTableInfo == null) { + throw new MPJException("未注册 mapper " + this.joinClass.getName()); + } + this.joinMapper = (MPJBaseMapper) SpringContentUtils.getApplicationContext().getBean(joinTableInfo.getMapperClass()); + } + return this.joinMapper; + } + + private TableInfo getTableInfo(Class clazz) { + TableInfo tableInfo = TableInfoHelper.getTableInfo(clazz); + if (tableInfo == null) { + throw new MPJException("未注册 mapper " + clazz.getName()); + } + return tableInfo; + } + + + public void fieldSet(Object o, Object val) { + try { + this.field.set(o, val); + } catch (Exception e) { + throw new MPJException("无法设置关联字段,请检查关联字段数据类型是否匹配 " + this.entityType.getName() + + " , " + this.field.getName() + " , " + o.getClass().getName()); + } + } + + public Object thisFieldGet(Object o) { + try { + return getThisField().get(o); + } catch (Exception e) { + throw new MPJException("无法获取当前关联字段,请检查关联字段是否匹配 " + this.entityType.getName() + " , " + + this.thisField.getName() + " , " + o.getClass().getName()); + } + } + + public Object joinFieldGet(Object o) { + try { + return getJoinField().get(o); + } catch (Exception e) { + throw new MPJException("无法设置关联字段,请检查关联字段数据类型是否匹配 " + this.joinClass.getName() + " , " + + this.joinField.getName() + " , " + o.getClass().getName()); + } + } +} diff --git a/src/main/java/com/baomidou/mybatisplus/core/metadata/MPJTableInfo.java b/src/main/java/com/baomidou/mybatisplus/core/metadata/MPJTableInfo.java new file mode 100644 index 0000000..a54a309 --- /dev/null +++ b/src/main/java/com/baomidou/mybatisplus/core/metadata/MPJTableInfo.java @@ -0,0 +1,38 @@ +package com.baomidou.mybatisplus.core.metadata; + +import lombok.AccessLevel; +import lombok.Data; +import lombok.Setter; +import lombok.experimental.Accessors; + +import java.util.List; + +/** + * 数据库表反射信息 + * + * @author yulichang + * @see TableInfo + * @since 1.2.0 + */ +@Data +@Setter(AccessLevel.PACKAGE) +@Accessors(chain = true) +public class MPJTableInfo { + + private TableInfo tableInfo; + + /** + * 是否包含映射注解 + */ + private boolean hasMapping; + + /** + * mapperClass + */ + private Class mapperClass; + + /** + * 包含映射注解的字段列表 + */ + private List fieldList; +} diff --git a/src/main/java/com/baomidou/mybatisplus/core/metadata/MPJTableInfoHelper.java b/src/main/java/com/baomidou/mybatisplus/core/metadata/MPJTableInfoHelper.java index e555896..e8f9f52 100644 --- a/src/main/java/com/baomidou/mybatisplus/core/metadata/MPJTableInfoHelper.java +++ b/src/main/java/com/baomidou/mybatisplus/core/metadata/MPJTableInfoHelper.java @@ -3,6 +3,8 @@ package com.baomidou.mybatisplus.core.metadata; import com.baomidou.mybatisplus.annotation.*; import com.baomidou.mybatisplus.core.config.GlobalConfig; import com.baomidou.mybatisplus.core.toolkit.*; +import com.github.yulichang.annotation.MPJMapping; +import org.apache.ibatis.builder.MapperBuilderAssistant; import org.apache.ibatis.logging.Log; import org.apache.ibatis.logging.LogFactory; import org.apache.ibatis.mapping.ResultFlag; @@ -38,7 +40,7 @@ public class MPJTableInfoHelper { /** * 储存反射类表信息 */ - private static final Map, TableInfo> TABLE_INFO_CACHE = new ConcurrentHashMap<>(); + private static final Map, MPJTableInfo> TABLE_INFO_CACHE = new ConcurrentHashMap<>(); /** * 默认表主键名称 @@ -54,13 +56,47 @@ public class MPJTableInfoHelper { * @param clazz 反射实体类 * @return 数据库表反射信息 */ - public static TableInfo getTableInfo(Class clazz) { + public static MPJTableInfo getTableInfo(Class clazz) { if (clazz == null || ReflectionKit.isPrimitiveOrWrapper(clazz) || clazz == String.class || clazz.isInterface()) { return null; } return TABLE_INFO_CACHE.get(clazz); } + /** + *

+ * 实体类反射获取表信息【初始化】 + *

+ * + * @param clazz 反射实体类 + * @param mapperClass mapperClass + */ + public synchronized static void initTableInfo(MapperBuilderAssistant builderAssistant, Class clazz, Class mapperClass) { + MPJTableInfo targetTableInfo = TABLE_INFO_CACHE.get(clazz); + final Configuration configuration = builderAssistant.getConfiguration(); + if (targetTableInfo != null) { + Configuration oldConfiguration = targetTableInfo.getTableInfo().getConfiguration(); + if (!oldConfiguration.equals(configuration)) { + // 不是同一个 Configuration,进行重新初始化 + initTableInfo(configuration, builderAssistant.getCurrentNamespace(), clazz, mapperClass); + } + return; + } + initTableInfo(configuration, builderAssistant.getCurrentNamespace(), clazz, mapperClass); + } + + + /** + *

+ * 获取所有实体映射表信息 + *

+ * + * @return 数据库表反射信息集合 + */ + public static List getTableInfos() { + return Collections.unmodifiableList(new ArrayList<>(TABLE_INFO_CACHE.values())); + } + /** *

* 实体类反射获取表信息【初始化】 @@ -69,13 +105,26 @@ public class MPJTableInfoHelper { * @param clazz 反射实体类 * @return 数据库表反射信息 */ - public synchronized static TableInfo initTableInfo(Configuration configuration, String currentNamespace, Class clazz) { - TableInfo info = TABLE_INFO_CACHE.get(clazz); + public synchronized static MPJTableInfo initTableInfo(Configuration configuration, String currentNamespace, Class clazz, Class mapperClass) { + MPJTableInfo info = TABLE_INFO_CACHE.get(clazz); if (info != null) { return info; } /* 没有获取到缓存信息,则初始化 */ - TableInfo tableInfo = new TableInfo(clazz); + MPJTableInfo mpjTableInfo = new MPJTableInfo(); + mpjTableInfo.setMapperClass(mapperClass); + TableInfo tableInfo = TableInfoHelper.getTableInfo(clazz); + if (tableInfo != null) { + mpjTableInfo.setTableInfo(tableInfo); + initMapping(mpjTableInfo); + /* 添加缓存 */ + TABLE_INFO_CACHE.put(clazz, mpjTableInfo); + return mpjTableInfo; + } + + + tableInfo = new TableInfo(clazz); + mpjTableInfo.setTableInfo(tableInfo); tableInfo.setCurrentNamespace(currentNamespace); tableInfo.setConfiguration(configuration); GlobalConfig globalConfig = GlobalConfigUtils.getGlobalConfig(configuration); @@ -86,17 +135,20 @@ public class MPJTableInfoHelper { List excludePropertyList = excludeProperty != null && excludeProperty.length > 0 ? Arrays.asList(excludeProperty) : Collections.emptyList(); /* 初始化字段相关 */ - initTableFields(clazz, globalConfig, tableInfo, excludePropertyList); + initTableFields(clazz, globalConfig, mpjTableInfo, excludePropertyList); /* 自动构建 resultMap */ initResultMapIfNeed(tableInfo); /* 添加缓存 */ - TABLE_INFO_CACHE.put(clazz, tableInfo); + TABLE_INFO_CACHE.put(clazz, mpjTableInfo); /* 缓存 lambda */ LambdaUtils.installCache(tableInfo); - return tableInfo; + + /* 初始化映射关系 */ + initMapping(mpjTableInfo); + return mpjTableInfo; } @@ -179,10 +231,6 @@ public class MPJTableInfoHelper { tableInfo.setTableName(targetTableName); - /* 开启了自定义 KEY 生成器 */ -// if (CollectionUtils.isNotEmpty(dbConfig.getKeyGenerators())) { -// tableInfo.setKeySequence(clazz.getAnnotation(KeySequence.class)); -// } return excludeProperty; } @@ -216,12 +264,12 @@ public class MPJTableInfoHelper { * * @param clazz 实体类 * @param globalConfig 全局配置 - * @param tableInfo 数据库表反射信息 + * @param mpjTableInfo 数据库表反射信息 */ - private static void initTableFields(Class clazz, GlobalConfig globalConfig, TableInfo tableInfo, List excludeProperty) { + private static void initTableFields(Class clazz, GlobalConfig globalConfig, MPJTableInfo mpjTableInfo, List excludeProperty) { /* 数据库全局配置 */ GlobalConfig.DbConfig dbConfig = globalConfig.getDbConfig(); - ReflectorFactory reflectorFactory = tableInfo.getConfiguration().getReflectorFactory(); + ReflectorFactory reflectorFactory = mpjTableInfo.getTableInfo().getConfiguration().getReflectorFactory(); Reflector reflector = reflectorFactory.findForClass(clazz); List list = getAllFields(clazz); // 标记是否读取到主键 @@ -244,31 +292,33 @@ public class MPJTableInfoHelper { if (isReadPK) { throw ExceptionUtils.mpe("@TableId can't more than one in Class: \"%s\".", clazz.getName()); } else { - initTableIdWithAnnotation(dbConfig, tableInfo, field, tableId, reflector); + initTableIdWithAnnotation(dbConfig, mpjTableInfo.getTableInfo(), field, tableId, reflector); isReadPK = true; continue; } } } else if (!isReadPK) { - isReadPK = initTableIdWithoutAnnotation(dbConfig, tableInfo, field, reflector); + isReadPK = initTableIdWithoutAnnotation(dbConfig, mpjTableInfo.getTableInfo(), field, reflector); if (isReadPK) { continue; } } + final TableField tableField = field.getAnnotation(TableField.class); /* 有 @TableField 注解的字段初始化 */ if (tableField != null) { - fieldList.add(new TableFieldInfo(dbConfig, tableInfo, field, tableField, reflector, existTableLogic)); + fieldList.add(new TableFieldInfo(dbConfig, mpjTableInfo.getTableInfo(), field, tableField, reflector, existTableLogic)); continue; } /* 无 @TableField 注解的字段初始化 */ - fieldList.add(new TableFieldInfo(dbConfig, tableInfo, field, reflector, existTableLogic)); + fieldList.add(new TableFieldInfo(dbConfig, mpjTableInfo.getTableInfo(), field, reflector, existTableLogic)); } /* 字段列表 */ - tableInfo.setFieldList(fieldList); + mpjTableInfo.getTableInfo().setFieldList(fieldList); + /* 未发现主键注解,提示警告信息 */ if (!isReadPK) { @@ -300,6 +350,10 @@ public class MPJTableInfoHelper { return list.stream().anyMatch(field -> field.isAnnotationPresent(TableLogic.class)); } + private static boolean isExistMapping(Class clazz) { + return ReflectionKit.getFieldList(ClassUtils.getUserClass(clazz)).stream().anyMatch(field -> field.isAnnotationPresent(MPJMapping.class)); + } + /** *

* 主键属性初始化 @@ -430,4 +484,27 @@ public class MPJTableInfoHelper { return (tableField == null || tableField.exist()); }).collect(toList()); } + + /** + * 初始化映射相关 + */ + public static void initMapping(MPJTableInfo mpjTableInfo) { + // 是否存在 @MPJMapping 注解 + boolean existMapping = isExistMapping(mpjTableInfo.getTableInfo().getEntityType()); + mpjTableInfo.setHasMapping(existMapping); + /* 关系映射初始化 */ + List mpjFieldList = new ArrayList<>(); + List fields = ReflectionKit.getFieldList(ClassUtils.getUserClass(mpjTableInfo.getTableInfo().getEntityType())); + for (Field field : fields) { + if (existMapping) { + MPJMapping mapping = field.getAnnotation(MPJMapping.class); + if (mapping != null) { + mpjFieldList.add(new MPJTableFieldInfo(mpjTableInfo.getTableInfo().getEntityType(), mapping, field)); + } + } + } + /* 映射字段列表 */ + mpjTableInfo.setFieldList(mpjFieldList); + } + } diff --git a/src/main/java/com/github/yulichang/annotation/MPJMapping.java b/src/main/java/com/github/yulichang/annotation/MPJMapping.java new file mode 100644 index 0000000..f1f60fd --- /dev/null +++ b/src/main/java/com/github/yulichang/annotation/MPJMapping.java @@ -0,0 +1,88 @@ +package com.github.yulichang.annotation; + + +import java.lang.annotation.*; + +/** + * 关系映射注解 + * + * @author yulichang + * @since 1.2.0 + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE}) +public @interface MPJMapping { + + /** + * 关联的数据库实体类 + */ + Class tag(); + + /** + * 当前类的属性数据结构 是否是Map 或 List + * 如果是 true 关联查询会调用 getMap() / listMaps() 等Map相关方法进行匹配 + * 如果是 false 关联查询会调用 getOne() / getById() / list() 等实体类相关方法进行匹配 + */ + boolean isMap() default false; + + /** + * 当前类的关联的字段名称 (是实体类字段名称而不是数据库字段名称) + * 默认获取当前类上定义的主键 @TableId + */ + String thisField() default ""; + + /** + * 关联类的字段名称 (是实体类字段名称而不是数据库字段名称) + * 默认获取关联类上定义的主键 @TableId + */ + String joinField() default ""; + + /** + * 针对查询结果map的时候使用 + * 默认为thisField对应的数据库列名 + *

+ * 如果此类是以map方式查询的 + * 并且查询出来的map的key不是thisField对应的数据库列名就需要设置 + */ + String thisMapKey() default ""; + + /** + * isMap为true时生效 + * 针对查询结果map的时候使用 + * 默认为joinField对应的数据库列名 + *

+ * 如果此类是以map方式查询的 + * 并且查询出来的map的key不是thisField对应的数据库列名就需要设置 + */ + String joinMapKsy() default ""; + + /** + * 映射表查询条件之 select + * 等效于 Wrappers.query().select(xxx); + */ + String select() default ""; + + /** + * 映射表查询条件之 first + * 等效于 Wrappers.query().first(xxx); + */ + String first() default ""; + + /** + * 映射表查询条件之 apply + * 等效于 Wrappers.query().apply(xxx); + */ + MPJMappingApply[] apply() default {}; + + /** + * 映射表查询条件 + */ + MPJMappingCondition[] condition() default {}; + + /** + * 映射表查询条件之 last + * 等效于 Wrappers.query().last(xxx); + */ + String last() default ""; +} diff --git a/src/main/java/com/github/yulichang/annotation/MPJMappingApply.java b/src/main/java/com/github/yulichang/annotation/MPJMappingApply.java new file mode 100644 index 0000000..a060ad2 --- /dev/null +++ b/src/main/java/com/github/yulichang/annotation/MPJMappingApply.java @@ -0,0 +1,21 @@ +package com.github.yulichang.annotation; + +/** + * 映射表条件 + * 用法参考 mybatis plus wrapper 的 .apply()方法 + * + * @author yulichang + * @since 1.2.0 + */ +public @interface MPJMappingApply { + + /** + * sql片段 + */ + String value(); + + /** + * .apply() 对应的可变参数 + */ + String[] args(); +} diff --git a/src/main/java/com/github/yulichang/annotation/MPJMappingCondition.java b/src/main/java/com/github/yulichang/annotation/MPJMappingCondition.java new file mode 100644 index 0000000..da024a5 --- /dev/null +++ b/src/main/java/com/github/yulichang/annotation/MPJMappingCondition.java @@ -0,0 +1,34 @@ +package com.github.yulichang.annotation; + +import com.baomidou.mybatisplus.core.enums.SqlKeyword; + +/** + * 映射表条件 + * + * @author yulichang + * @since 1.2.0 + */ +public @interface MPJMappingCondition { + + /** + * 条件枚举 + * 目前只实现了 = != > >= < <= + * 其他的暂未实现 TODO + * + * @see SqlKeyword + */ + SqlKeyword keyWord() default SqlKeyword.EQ; + + /** + * 数据库列名 + */ + String column(); + + /** + * 对应的值 + * 一般是一个值 + * 如果条件是 between 会取前两个 + * 如果条件是 in 就会取全部 + */ + String[] value(); +} diff --git a/src/main/java/com/github/yulichang/base/MPJBaseDeepService.java b/src/main/java/com/github/yulichang/base/MPJBaseDeepService.java new file mode 100644 index 0000000..7ed7143 --- /dev/null +++ b/src/main/java/com/github/yulichang/base/MPJBaseDeepService.java @@ -0,0 +1,307 @@ +package com.github.yulichang.base; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.enums.SqlKeyword; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.metadata.MPJTableFieldInfo; +import com.baomidou.mybatisplus.core.metadata.MPJTableInfo; +import com.baomidou.mybatisplus.core.metadata.MPJTableInfoHelper; +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.IService; +import com.github.yulichang.annotation.MPJMapping; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * 深度查询 + *

+ * 对配置了@MPJMapping注解的字段进行查询 + * 目前查询深度只支持2级(只解析当前实体类的MPJMapping注解,不会对查询结果再次解析注解) + * 多级查询可能存在循环引用的问题,也可能会导致全量查询 + * + * @author yulichang + * @see MPJMapping + * @since 1.2.0 + */ +@SuppressWarnings("unused") +public interface MPJBaseDeepService extends IService { + + Class currentModelClass(); + + /** + * 根据 ID 深度查询 + * + * @param id 主键ID列表 + */ + default T getByIdDeep(Serializable id) { + return queryMapping(getById(id)); + } + + + /** + * 查询(根据ID 批量查询) + * + * @param idList 主键ID列表 + */ + default List listByIdsDeep(Collection idList) { + return queryMapping(listByIds(idList)); + } + + /** + * 查询(根据 columnMap 条件) + * + * @param columnMap 表字段 map 对象 + */ + default List listByMapDeep(Map columnMap) { + return queryMapping(listByMap(columnMap)); + } + + + /** + * 根据 Wrapper,查询一条记录
+ *

结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")

+ * + * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper} + */ + default T getOneDeep(Wrapper queryWrapper) { + return queryMapping(getOne(queryWrapper)); + } + + + /** + * 根据 Wrapper,查询一条记录 + * + * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper} + * @param throwEx 有多个 result 是否抛出异常 + */ + default T getOneDeep(Wrapper queryWrapper, boolean throwEx) { + return queryMapping(getOne(queryWrapper, throwEx)); + } + + /** + * 根据 Wrapper,查询一条记录 + * + * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper} + */ + default Map getMapDeep(Wrapper queryWrapper) { + Map map = getMap(queryWrapper); + if (CollectionUtils.isNotEmpty(map)) { + MPJTableInfo tableInfo = MPJTableInfoHelper.getTableInfo(currentModelClass()); + if (tableInfo.isHasMapping()) { + for (MPJTableFieldInfo fieldInfo : tableInfo.getFieldList()) { + Object o = map.get(fieldInfo.getThisMapKey()); + if (o != null) { + map.put(fieldInfo.getField().getName(), fieldInfo.getJoinMapper() + .mappingWrapperConstructor(fieldInfo.isCollection(), fieldInfo.isFieldIsMap(), SqlKeyword.EQ, + fieldInfo.getJoinColumn(), o, fieldInfo)); + } + } + } + } + return map; + } + + + /** + * 查询列表 + * + * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper} + */ + default List listDeep(Wrapper queryWrapper) { + return queryMapping(list(queryWrapper)); + } + + /** + * 查询所有 + * + * @see Wrappers#emptyWrapper() + */ + default List listDeep() { + return queryMapping(list()); + } + + /** + * 翻页查询 + * + * @param page 翻页对象 + * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper} + */ + default > E pageDeep(E page, Wrapper queryWrapper) { + E e = page(page, queryWrapper); + if (CollectionUtils.isNotEmpty(e.getRecords())) { + queryMapping(e.getRecords()); + } + return e; + } + + /** + * 无条件翻页查询 + * + * @param page 翻页对象 + * @see Wrappers#emptyWrapper() + */ + default > E pageDeep(E page) { + E e = page(page); + if (CollectionUtils.isNotEmpty(e.getRecords())) { + queryMapping(e.getRecords()); + } + return e; + } + + /** + * 查询列表 + * + * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper} + */ + default List> listMapsDeep(Wrapper queryWrapper) { + return queryMapMapping(listMaps(queryWrapper)); + } + + /** + * 查询所有列表 + * + * @see Wrappers#emptyWrapper() + */ + default List> listMapsDeep() { + return queryMapMapping(listMaps()); + } + + + /** + * 翻页查询 + * + * @param page 翻页对象 + * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper} + */ + default >> E pageMapsDeep(E page, Wrapper queryWrapper) { + E e = pageMaps(page, queryWrapper); + if (CollectionUtils.isNotEmpty(e.getRecords())) { + queryMapMapping(e.getRecords()); + } + return e; + } + + /** + * 无条件翻页查询 + * + * @param page 翻页对象 + * @see Wrappers#emptyWrapper() + */ + default >> E pageMapsDeep(E page) { + E e = pageMaps(page); + if (CollectionUtils.isNotEmpty(e.getRecords())) { + queryMapMapping(e.getRecords()); + } + return e; + } + + /** + * 查询映射关系 + * 对结果进行二次查询 + * 可以自行查询然后在通过此方法进行二次查询 + * + * @param t 第一次查询结果 + */ + default T queryMapping(T t) { + if (t == null) { + return null; + } + MPJTableInfo tableInfo = MPJTableInfoHelper.getTableInfo(currentModelClass()); + if (tableInfo.isHasMapping()) { + for (MPJTableFieldInfo fieldInfo : tableInfo.getFieldList()) { + Object get = fieldInfo.thisFieldGet(t); + if (get != null) { + fieldInfo.fieldSet(t, fieldInfo.getJoinMapper().mappingWrapperConstructor(fieldInfo.isCollection(), + fieldInfo.isFieldIsMap(), SqlKeyword.EQ, fieldInfo.getJoinColumn(), + get, fieldInfo)); + } + } + } + return t; + } + + /** + * 查询映射关系 + * 对结果进行二次查询 + * 可以自行查询然后在通过此方法进行二次查询 + * + * @param list 第一次查询结果 + */ + default List queryMapping(List list) { + if (CollectionUtils.isEmpty(list)) { + return list; + } + MPJTableInfo tableInfo = MPJTableInfoHelper.getTableInfo(currentModelClass()); + if (tableInfo.isHasMapping()) { + for (MPJTableFieldInfo fieldInfo : tableInfo.getFieldList()) { + List itemList = list.stream().map(fieldInfo::thisFieldGet).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(itemList)) { + List joinList = (List) fieldInfo.getJoinMapper().mappingWrapperConstructor(true, + fieldInfo.isFieldIsMap(), SqlKeyword.IN, fieldInfo.getJoinColumn(), itemList, fieldInfo); + list.forEach(i -> { + Stream stream = joinList.stream().filter(j -> + fieldInfo.joinFieldGet(j).equals(fieldInfo.thisFieldGet(i))); + fieldInfo.fieldSet(i, fieldInfo.isCollection() ? stream.collect(Collectors.toList()) : + stream.findFirst().orElse(null)); + }); + } else { + list.forEach(i -> fieldInfo.fieldSet(i, new ArrayList<>())); + } + } + } + return list; + } + + /** + * 查询映射关系 + * 对结果进行二次查询 + * 可以自行查询然后在通过此方法进行二次查询 + * + * @param list 第一次查询结果 + */ + @SuppressWarnings("unchecked") + default List> queryMapMapping(List> list) { + if (CollectionUtils.isEmpty(list)) { + return list; + } + MPJTableInfo tableInfo = MPJTableInfoHelper.getTableInfo(currentModelClass()); + if (tableInfo.isHasMapping()) { + for (MPJTableFieldInfo fieldInfo : tableInfo.getFieldList()) { + List itemList = list.stream().map(m -> m.get(fieldInfo.getThisMapKey())).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(itemList)) { + if (fieldInfo.isFieldIsMap()) { + List> joinList = (List>) fieldInfo.getJoinMapper().mappingWrapperConstructor(true, + fieldInfo.isFieldIsMap(), SqlKeyword.IN, fieldInfo.getJoinColumn(), itemList, fieldInfo); + list.forEach(i -> { + Stream> stream = joinList.stream().filter(j -> j.containsKey(fieldInfo.getJoinMapKey()) + && j.get(fieldInfo.getJoinMapKey()).equals(i.get(fieldInfo.getThisMapKey()))); + i.put(fieldInfo.getField().getName(), fieldInfo.isCollection() ? stream.collect(Collectors.toList()) : + stream.findFirst().orElse(null)); + }); + } else { + List joinList = (List) fieldInfo.getJoinMapper().mappingWrapperConstructor(true, + fieldInfo.isFieldIsMap(), SqlKeyword.IN, fieldInfo.getJoinColumn(), itemList, fieldInfo); + list.forEach(i -> { + Stream stream = joinList.stream().filter(j -> { + Object o = fieldInfo.joinFieldGet(j); + return o != null && o.equals(i.get(fieldInfo.getThisMapKey())); + }); + i.put(fieldInfo.getField().getName(), fieldInfo.isCollection() ? stream.collect(Collectors.toList()) : + stream.findFirst().orElse(null)); + }); + } + } else { + list.forEach(i -> i.put(fieldInfo.getField().getName(), new ArrayList<>())); + } + } + } + return list; + } +} diff --git a/src/main/java/com/github/yulichang/base/MPJBaseJoinService.java b/src/main/java/com/github/yulichang/base/MPJBaseJoinService.java new file mode 100644 index 0000000..c475364 --- /dev/null +++ b/src/main/java/com/github/yulichang/base/MPJBaseJoinService.java @@ -0,0 +1,65 @@ +package com.github.yulichang.base; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.github.yulichang.interfaces.MPJBaseJoin; + +import java.util.List; +import java.util.Map; + +/** + * @author yulichang + * @see IService + */ +@SuppressWarnings("unused") +public interface MPJBaseJoinService extends IService { + + /** + * 根据 Wrapper 条件,查询总记录数 + */ + default Integer selectJoinCount(MPJBaseJoin wrapper) { + return ((MPJBaseMapper) getBaseMapper()).selectJoinCount(wrapper); + } + + /** + * 连接查询返回一条记录 + */ + default DTO selectJoinOne(Class clazz, MPJBaseJoin wrapper) { + return ((MPJBaseMapper) getBaseMapper()).selectJoinOne(clazz, wrapper); + } + + /** + * 连接查询返回集合 + */ + default List selectJoinList(Class clazz, MPJBaseJoin wrapper) { + return ((MPJBaseMapper) getBaseMapper()).selectJoinList(clazz, wrapper); + } + + /** + * 连接查询返回集合并分页 + */ + default > IPage selectJoinListPage(P page, Class clazz, MPJBaseJoin wrapper) { + return ((MPJBaseMapper) getBaseMapper()).selectJoinPage(page, clazz, wrapper); + } + + /** + * 连接查询返回Map + */ + default Map selectJoinMap(MPJBaseJoin wrapper) { + return ((MPJBaseMapper) getBaseMapper()).selectJoinMap(wrapper); + } + + /** + * 连接查询返回Map集合 + */ + default List> selectJoinMaps(MPJBaseJoin wrapper) { + return ((MPJBaseMapper) getBaseMapper()).selectJoinMaps(wrapper); + } + + /** + * 连接查询返回Map集合并分页 + */ + default

>> IPage> selectJoinMapsPage(P page, MPJBaseJoin wrapper) { + return ((MPJBaseMapper) getBaseMapper()).selectJoinMapsPage(page, wrapper); + } +} diff --git a/src/main/java/com/github/yulichang/base/MPJBaseMapper.java b/src/main/java/com/github/yulichang/base/MPJBaseMapper.java index d6e5c90..0e435eb 100644 --- a/src/main/java/com/github/yulichang/base/MPJBaseMapper.java +++ b/src/main/java/com/github/yulichang/base/MPJBaseMapper.java @@ -1,7 +1,11 @@ package com.github.yulichang.base; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.enums.SqlKeyword; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.metadata.MPJMappingWrapper; +import com.baomidou.mybatisplus.core.metadata.MPJTableFieldInfo; import com.baomidou.mybatisplus.core.toolkit.Constants; import com.github.yulichang.interfaces.MPJBaseJoin; import com.github.yulichang.toolkit.Constant; @@ -73,4 +77,47 @@ public interface MPJBaseMapper extends BaseMapper { */

> IPage> selectJoinMapsPage(P page, @Param(Constants.WRAPPER) MPJBaseJoin wrapper); + + + /** + * 映射 wrapper 构造器 + * 仅对使用 @MPJMapping 时使用 + */ + default Object mappingWrapperConstructor(boolean isCollection, boolean selectMap, SqlKeyword keyword, + String column, Object val, MPJTableFieldInfo fieldInfo) { + MPJMappingWrapper infoWrapper = fieldInfo.getWrapper(); + MappingQuery wrapper = new MappingQuery<>(); + if (infoWrapper.isHasCondition()) { + infoWrapper.getConditionList().forEach(c -> wrapper.addCondition(true, c.getColumn(), + c.getKeyword(), c.getVal())); + } + wrapper.eq(SqlKeyword.EQ == keyword, column, val) + .first(infoWrapper.isHasFirst(), infoWrapper.getFirst()) + .last(infoWrapper.isHasLast(), infoWrapper.getLast()); + if (SqlKeyword.IN == keyword) { + wrapper.in(column, (List) val); + } + if (infoWrapper.isHasSelect()) { + wrapper.select(infoWrapper.getSelect()); + } + if (infoWrapper.isHasApply()) { + infoWrapper.getApplyList().forEach(a -> wrapper.apply(a.getSql(), (Object[]) a.getVal())); + } + + + if (selectMap) { + return isCollection ? selectMaps(wrapper) : selectMaps(wrapper).stream().findFirst().orElse(null); + } + return isCollection ? selectList(wrapper) : selectOne(wrapper); + } + + /** + * 公开 addCondition 方法 + */ + class MappingQuery extends QueryWrapper { + @Override + public QueryWrapper addCondition(boolean condition, String column, SqlKeyword sqlKeyword, Object val) { + return super.addCondition(condition, column, sqlKeyword, val); + } + } } diff --git a/src/main/java/com/github/yulichang/base/MPJBaseService.java b/src/main/java/com/github/yulichang/base/MPJBaseService.java index 1d42595..e9092a6 100644 --- a/src/main/java/com/github/yulichang/base/MPJBaseService.java +++ b/src/main/java/com/github/yulichang/base/MPJBaseService.java @@ -1,50 +1,12 @@ package com.github.yulichang.base; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.service.IService; -import com.github.yulichang.interfaces.MPJBaseJoin; - -import java.util.List; -import java.util.Map; - /** + * 基础service + * 目前包含两个模块 连表查询 和 关系映射 + * * @author yulichang - * @see IService + * @see MPJBaseJoinService + * @see MPJBaseDeepService */ -public interface MPJBaseService extends IService { - - /** - * 根据 Wrapper 条件,查询总记录数 - */ - Integer selectJoinCount(MPJBaseJoin wrapper); - - /** - * 连接查询返回一条记录 - */ - DTO selectJoinOne(Class clazz, MPJBaseJoin wrapper); - - /** - * 连接查询返回集合 - */ - List selectJoinList(Class clazz, MPJBaseJoin wrapper); - - /** - * 连接查询返回集合并分页 - */ - > IPage selectJoinListPage(P page, Class clazz, MPJBaseJoin wrapper); - - /** - * 连接查询返回Map - */ - Map selectJoinMap(MPJBaseJoin wrapper); - - /** - * 连接查询返回Map集合 - */ - List> selectJoinMaps(MPJBaseJoin wrapper); - - /** - * 连接查询返回Map集合并分页 - */ -

>> IPage> selectJoinMapsPage(P page, MPJBaseJoin wrapper); +public interface MPJBaseService extends MPJBaseJoinService, MPJBaseDeepService { } diff --git a/src/main/java/com/github/yulichang/base/MPJBaseServiceImpl.java b/src/main/java/com/github/yulichang/base/MPJBaseServiceImpl.java index b0c0e00..f6b01f1 100644 --- a/src/main/java/com/github/yulichang/base/MPJBaseServiceImpl.java +++ b/src/main/java/com/github/yulichang/base/MPJBaseServiceImpl.java @@ -1,76 +1,16 @@ package com.github.yulichang.base; -import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.github.yulichang.interfaces.MPJBaseJoin; -import com.github.yulichang.toolkit.ReflectionKit; - -import java.util.List; -import java.util.Map; /** * @author yulichang * @see ServiceImpl */ -@SuppressWarnings("unchecked") +@SuppressWarnings("unused") public class MPJBaseServiceImpl, T> extends ServiceImpl implements MPJBaseService { - /** - * mybatis plus 3.4.3 bug - *

- * https://gitee.com/baomidou/mybatis-plus/issues/I3SE8R - *

- * https://gitee.com/baomidou/mybatis-plus/commit/7210b461b23211e6b95ca6de2d846aa392bdc28c - */ @Override - protected Class currentMapperClass() { - return (Class) ReflectionKit.getSuperClassGenericType(this.getClass(), ServiceImpl.class, 0); - } - - /** - * mybatis plus 3.4.3 bug - *

- * https://gitee.com/baomidou/mybatis-plus/issues/I3SE8R - *

- * https://gitee.com/baomidou/mybatis-plus/commit/7210b461b23211e6b95ca6de2d846aa392bdc28c - */ - @Override - protected Class currentModelClass() { - return (Class) ReflectionKit.getSuperClassGenericType(this.getClass(), ServiceImpl.class, 1); - } - - @Override - public Integer selectJoinCount(MPJBaseJoin wrapper) { - return baseMapper.selectJoinCount(wrapper); - } - - @Override - public DTO selectJoinOne(Class clazz, MPJBaseJoin wrapper) { - return baseMapper.selectJoinOne(clazz, wrapper); - } - - @Override - public List selectJoinList(Class clazz, MPJBaseJoin wrapper) { - return baseMapper.selectJoinList(clazz, wrapper); - } - - @Override - public > IPage selectJoinListPage(P page, Class clazz, MPJBaseJoin wrapper) { - return baseMapper.selectJoinPage(page, clazz, wrapper); - } - - @Override - public Map selectJoinMap(MPJBaseJoin wrapper) { - return baseMapper.selectJoinMap(wrapper); - } - - @Override - public List> selectJoinMaps(MPJBaseJoin wrapper) { - return baseMapper.selectJoinMaps(wrapper); - } - - @Override - public

>> IPage> selectJoinMapsPage(P page, MPJBaseJoin wrapper) { - return baseMapper.selectJoinMapsPage(page, wrapper); + public Class currentModelClass() { + return super.currentModelClass(); } } diff --git a/src/main/java/com/github/yulichang/injector/MPJSqlInjector.java b/src/main/java/com/github/yulichang/injector/MPJSqlInjector.java index b3b6522..e7f4e65 100644 --- a/src/main/java/com/github/yulichang/injector/MPJSqlInjector.java +++ b/src/main/java/com/github/yulichang/injector/MPJSqlInjector.java @@ -2,20 +2,12 @@ package com.github.yulichang.injector; import com.baomidou.mybatisplus.core.injector.AbstractMethod; import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector; -import com.baomidou.mybatisplus.core.mapper.Mapper; -import com.baomidou.mybatisplus.core.metadata.TableInfo; -import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; -import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; -import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils; +import com.baomidou.mybatisplus.core.metadata.MPJTableInfoHelper; import com.github.yulichang.method.*; -import com.github.yulichang.toolkit.ReflectionKit; import org.apache.ibatis.builder.MapperBuilderAssistant; -import org.apache.ibatis.logging.Log; -import org.apache.ibatis.logging.LogFactory; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import java.util.List; -import java.util.Set; /** * SQL 注入器 @@ -25,7 +17,6 @@ import java.util.Set; */ @ConditionalOnMissingBean(DefaultSqlInjector.class) public class MPJSqlInjector extends DefaultSqlInjector { - private static final Log logger = LogFactory.getLog(MPJSqlInjector.class); @Override public List getMethodList(Class mapperClass) { @@ -40,30 +31,9 @@ public class MPJSqlInjector extends DefaultSqlInjector { return list; } - /** - * mybatis plus 3.4.3 bug - *

- * https://gitee.com/baomidou/mybatis-plus/issues/I3SE8R - *

- * https://gitee.com/baomidou/mybatis-plus/commit/7210b461b23211e6b95ca6de2d846aa392bdc28c - */ @Override public void inspectInject(MapperBuilderAssistant builderAssistant, Class mapperClass) { - Class modelClass = ReflectionKit.getSuperClassGenericType(mapperClass, Mapper.class, 0); - if (modelClass != null) { - String className = mapperClass.toString(); - Set mapperRegistryCache = GlobalConfigUtils.getMapperRegistryCache(builderAssistant.getConfiguration()); - if (!mapperRegistryCache.contains(className)) { - List methodList = this.getMethodList(mapperClass); - if (CollectionUtils.isNotEmpty(methodList)) { - TableInfo tableInfo = TableInfoHelper.initTableInfo(builderAssistant, modelClass); - // 循环注入自定义方法 - methodList.forEach(m -> m.inject(builderAssistant, mapperClass, modelClass, tableInfo)); - } else { - logger.debug(mapperClass + ", No effective injection method was found."); - } - mapperRegistryCache.add(className); - } - } + super.inspectInject(builderAssistant, mapperClass); + MPJTableInfoHelper.initTableInfo(builderAssistant, extractModelClass(mapperClass), mapperClass); } } diff --git a/src/main/java/com/github/yulichang/interceptor/MPJInterceptor.java b/src/main/java/com/github/yulichang/interceptor/MPJInterceptor.java index 3f961a3..1be1daf 100644 --- a/src/main/java/com/github/yulichang/interceptor/MPJInterceptor.java +++ b/src/main/java/com/github/yulichang/interceptor/MPJInterceptor.java @@ -1,5 +1,6 @@ package com.github.yulichang.interceptor; +import com.baomidou.mybatisplus.core.metadata.MPJTableInfo; import com.baomidou.mybatisplus.core.metadata.MPJTableInfoHelper; import com.baomidou.mybatisplus.core.metadata.TableInfo; import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; @@ -116,13 +117,13 @@ public class MPJInterceptor implements Interceptor { if (tableInfo != null && tableInfo.isAutoInitResultMap() && tableInfo.getEntityType() == resultType) { return ms.getConfiguration().getResultMap(tableInfo.getResultMap()); } - TableInfo infoDTO = MPJTableInfoHelper.getTableInfo(resultType); + MPJTableInfo infoDTO = MPJTableInfoHelper.getTableInfo(resultType); if (infoDTO == null) { infoDTO = MPJTableInfoHelper.initTableInfo(ms.getConfiguration(), - ms.getId().substring(0, ms.getId().lastIndexOf(".")), resultType); + ms.getId().substring(0, ms.getId().lastIndexOf(".")), resultType, null); } - if (infoDTO.isAutoInitResultMap()) { - return ms.getConfiguration().getResultMap(infoDTO.getResultMap()); + if (infoDTO.getTableInfo().isAutoInitResultMap()) { + return ms.getConfiguration().getResultMap(infoDTO.getTableInfo().getResultMap()); } return new ResultMap.Builder(ms.getConfiguration(), ms.getId(), resultType, EMPTY_RESULT_MAPPING).build(); } diff --git a/src/main/java/com/github/yulichang/toolkit/SpringContentUtils.java b/src/main/java/com/github/yulichang/toolkit/SpringContentUtils.java new file mode 100644 index 0000000..7beb082 --- /dev/null +++ b/src/main/java/com/github/yulichang/toolkit/SpringContentUtils.java @@ -0,0 +1,25 @@ +package com.github.yulichang.toolkit; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; + +/** + * spring容器工具类 + * + * @author yulichang + * @since 1.2.0 + */ +public class SpringContentUtils implements ApplicationContextAware { + + private static ApplicationContext context; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + context = applicationContext; + } + + public static ApplicationContext getApplicationContext() { + return context; + } +} diff --git a/src/main/resources/META-INF/spring.factories b/src/main/resources/META-INF/spring.factories index 37270fe..2ba1665 100644 --- a/src/main/resources/META-INF/spring.factories +++ b/src/main/resources/META-INF/spring.factories @@ -1,4 +1,5 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.github.yulichang.interceptor.MPJInterceptor,\ com.github.yulichang.injector.MPJSqlInjector,\ - com.github.yulichang.config.InterceptorConfig + com.github.yulichang.config.InterceptorConfig,\ + com.github.yulichang.toolkit.SpringContentUtils