diff --git a/src/main/java/com/github/yulichang/interceptor/MPJInterceptor.java b/src/main/java/com/github/yulichang/interceptor/MPJInterceptor.java index 82a4faf..e461031 100644 --- a/src/main/java/com/github/yulichang/interceptor/MPJInterceptor.java +++ b/src/main/java/com/github/yulichang/interceptor/MPJInterceptor.java @@ -1,13 +1,9 @@ package com.github.yulichang.interceptor; -import com.baomidou.mybatisplus.annotation.TableField; 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.CollectionUtils; -import com.baomidou.mybatisplus.core.toolkit.Constants; -import com.baomidou.mybatisplus.core.toolkit.StringPool; -import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.baomidou.mybatisplus.core.toolkit.*; import com.github.yulichang.interfaces.MPJBaseJoin; import com.github.yulichang.method.MPJResultType; import com.github.yulichang.toolkit.Constant; @@ -37,7 +33,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; /** * 连表拦截器 @@ -58,6 +53,11 @@ public class MPJInterceptor implements Interceptor { */ private static final Map> MS_CACHE = new ConcurrentHashMap<>(); + /** + * 打印 MPJ resultMap + */ + private static final boolean printResultMap = false; + @Override @SuppressWarnings({"Java8MapApi", "unchecked"}) public Object intercept(Invocation invocation) throws Throwable { @@ -137,91 +137,134 @@ public class MPJInterceptor implements Interceptor { builder.keyProperty(String.join(StringPool.COMMA, ms.getKeyProperties())); } List resultMaps = new ArrayList<>(); - resultMaps.add(buildResultMap(ms, resultType, ew)); + ResultMap resultMap = buildResultMap(ms, resultType, ew); + resultMaps.add(resultMap); + printResultMap(resultMap); builder.resultMaps(resultMaps); return builder.build(); } /** - * 构建resultMap + * 构建resultMap TODO 可以用lambda简化代码 */ - @SuppressWarnings({"rawtypes", "unchecked", "ConstantConditions"}) + @SuppressWarnings({"rawtypes", "unchecked"}) private ResultMap buildResultMap(MappedStatement ms, Class resultType, Object obj) { TableInfo tableInfo = TableInfoHelper.getTableInfo(resultType); - if (tableInfo == null || !(obj instanceof MPJLambdaWrapper)) { - return getDefaultResultMap(tableInfo, ms, resultType); - } - MPJLambdaWrapper wrapper = (MPJLambdaWrapper) obj; String currentNamespace = ms.getResource().split(StringPool.SPACE)[0]; String id = currentNamespace + StringPool.DOT + Constants.MYBATIS_PLUS + StringPool.UNDERSCORE + resultType.getSimpleName(); + + if (!(obj instanceof MPJLambdaWrapper)) { + return getDefaultResultMap(tableInfo, ms, resultType, id); + } + MPJLambdaWrapper wrapper = (MPJLambdaWrapper) obj; + Map fieldMap = ReflectionKit.getFieldMap(resultType); + if (wrapper.isResultMap()) { //TODO - //添加 collection 标签 - return new ResultMap.Builder(ms.getConfiguration(), ms.getId(), resultType, EMPTY_RESULT_MAPPING).build(); + return new ResultMap.Builder(ms.getConfiguration(), id, resultType, EMPTY_RESULT_MAPPING).build(); } else { List columnList = wrapper.getSelectColumns(); - List resultMappings = new ArrayList<>(); + List resultMappings = new ArrayList<>(columnList.size()); columnList.forEach(i -> { - //别名优先 + TableFieldInfo info = i.getTableFieldInfo(); if (StringUtils.isNotBlank(i.getAlias())) { - resultMappings.add(new ResultMapping.Builder(ms.getConfiguration(), i.getAlias()) - .column(i.getColumnName()).build()); - } else if (i.getTableFieldInfo() != null) { - //其次field info - TableFieldInfo info = i.getTableFieldInfo(); - if (info.getTypeHandler() != null && info.getTypeHandler() != UnknownTypeHandler.class) { - TypeHandlerRegistry registry = ms.getConfiguration().getTypeHandlerRegistry(); - TypeHandler typeHandler = registry.getMappingTypeHandler(info.getTypeHandler()); - if (typeHandler == null) { - typeHandler = registry.getInstance(info.getPropertyType(), info.getTypeHandler()); + //优先别名查询 selectFunc selectAs + ResultMapping.Builder builder = new ResultMapping.Builder(ms.getConfiguration(), i.getAlias(), + i.getAlias(), getAliasField(resultType, fieldMap, i.getAlias())); + if (i.getFuncEnum() == null || StringUtils.isBlank(i.getFuncEnum().getSql())) { + if (info != null && info.getTypeHandler() != null && info.getTypeHandler() != UnknownTypeHandler.class) { + Field f = fieldMap.get(i.getAlias()); + if (f.getType() == info.getField().getType()) { + builder.typeHandler(getTypeHandler(ms, info)); + } } - resultMappings.add(new ResultMapping.Builder(ms.getConfiguration(), info.getProperty(), - info.getColumn(), info.getPropertyType()) - .typeHandler(typeHandler).build()); + } + resultMappings.add(builder.build()); + } else if (info != null) { + // select selectAll selectAsClass + if (i.getFuncEnum() == null || StringUtils.isBlank(i.getFuncEnum().getSql())) { + ResultMapping.Builder builder = new ResultMapping.Builder(ms.getConfiguration(), info.getProperty(), + info.getColumn(), info.getPropertyType()); + if (info.getTypeHandler() != null && info.getTypeHandler() != UnknownTypeHandler.class) { + Field f = fieldMap.get(info.getProperty()); + if (f != null && f.getType() == info.getField().getType()) { + builder.typeHandler(getTypeHandler(ms, info)); + } + } + resultMappings.add(builder.build()); } else { - resultMappings.add(new ResultMapping.Builder(ms.getConfiguration(), info.getProperty(), - info.getColumn(), info.getPropertyType()).build()); + resultMappings.add(new ResultMapping.Builder(ms.getConfiguration(), info.getProperty(), info.getColumn(), info.getPropertyType()).build()); } } else { - //最后取值 - TableFieldInfo info = tableInfo.getFieldList().stream().filter(t -> t.getColumn().equals(i.getColumnName())) - .findFirst().orElseGet(null); - if (info != null && Objects.equals(tableInfo.getKeyColumn(), i.getColumnName())) { - resultMappings.add(new ResultMapping.Builder(ms.getConfiguration(), tableInfo.getKeyProperty(), - tableInfo.getKeyColumn(), tableInfo.getKeyType()).build()); - } else if (info != null) { - resultMappings.add(new ResultMapping.Builder(ms.getConfiguration(), info.getProperty(), - info.getColumn(), info.getPropertyType()).build()); - } else { - resultMappings.add(new ResultMapping.Builder(ms.getConfiguration(), i.getColumnName()) - .column(i.getColumnName()).build()); - } + // 主键列 + resultMappings.add(new ResultMapping.Builder(ms.getConfiguration(), i.getTagProperty(), i.getColumnName(), + getAliasField(resultType, fieldMap, i.getTagProperty())).build()); } }); + //移除result中不存在的标签 + resultMappings.removeIf(i -> !fieldMap.containsKey(i.getProperty())); return new ResultMap.Builder(ms.getConfiguration(), id, resultType, resultMappings).build(); } } + /** + * 获取字段typeHandle + */ + private TypeHandler getTypeHandler(MappedStatement ms, TableFieldInfo info) { + TypeHandlerRegistry registry = ms.getConfiguration().getTypeHandlerRegistry(); + TypeHandler typeHandler = registry.getMappingTypeHandler(info.getTypeHandler()); + if (typeHandler == null) { + typeHandler = registry.getInstance(info.getPropertyType(), info.getTypeHandler()); + } + return typeHandler; + } - //TODO 可以加缓存 - private ResultMap getDefaultResultMap(TableInfo tableInfo, MappedStatement ms, Class resultType) { + + /** + * 获取非lambda的resultMap + */ + private ResultMap getDefaultResultMap(TableInfo tableInfo, MappedStatement ms, Class resultType, String id) { if (tableInfo != null && tableInfo.isAutoInitResultMap()) { - //补充不全的属性 + //补充不全的属性 并且是基础数据类型及其包装类 ResultMap resultMap = ms.getConfiguration().getResultMap(tableInfo.getResultMap()); List resultMappings = resultMap.getResultMappings(); - List notExistField = ReflectionKit.getFieldList(resultType).stream().filter(i -> - !i.getAnnotation(TableField.class).exist()).collect(Collectors.toList()); - if (CollectionUtils.isNotEmpty(notExistField)) { + List fieldList = ReflectionKit.getFieldList(resultType); + fieldList.removeIf(i -> resultMappings.stream().anyMatch(r -> i.getName().equals(r.getProperty()))); + if (CollectionUtils.isNotEmpty(fieldList)) { //复制已有的resultMapping List resultMappingList = new ArrayList<>(resultMappings); //复制不存在的resultMapping - for (Field i : notExistField) { + for (Field i : fieldList) { resultMappingList.add(new ResultMapping.Builder(ms.getConfiguration(), i.getName(), i.getName(), i.getType()).build()); } - return new ResultMap.Builder(ms.getConfiguration(), ms.getId(), resultType, resultMappingList).build(); + return new ResultMap.Builder(ms.getConfiguration(), id, resultType, resultMappingList).build(); } } - return new ResultMap.Builder(ms.getConfiguration(), ms.getId(), resultType, EMPTY_RESULT_MAPPING).build(); + return new ResultMap.Builder(ms.getConfiguration(), id, resultType, EMPTY_RESULT_MAPPING).build(); + } + + /** + * 获取result指定名称的字段 + */ + private Class getAliasField(Class resultType, Map fieldMap, String alias) { + Field field = fieldMap.get(alias); + Assert.notNull(field, "Result Class <%s> not find Field <%s>", resultType.getSimpleName(), alias); + return field.getType(); + } + + /** + * 打印resultMap + * 先打开 mybatis plus 日志, 在设置 printResultMap = true 才会打印 + */ + private void printResultMap(ResultMap resultMap) { + if (resultMap == null || !printResultMap) + return; + logger.debug("===================== MPJ resultMap ========================="); + List mappings = resultMap.getResultMappings(); + logger.debug(String.format(" ", resultMap.getId(), resultMap.getType().getName())); + mappings.forEach(i -> logger.debug(String.format(" ", i.getProperty(), i.getColumn(), i.getJavaType(), i.getTypeHandler()))); + logger.debug(" "); + logger.debug("===================== end ========================="); } } diff --git a/src/main/java/com/github/yulichang/toolkit/LambdaUtils.java b/src/main/java/com/github/yulichang/toolkit/LambdaUtils.java index 7efc9a1..fe30543 100644 --- a/src/main/java/com/github/yulichang/toolkit/LambdaUtils.java +++ b/src/main/java/com/github/yulichang/toolkit/LambdaUtils.java @@ -4,8 +4,8 @@ package com.github.yulichang.toolkit; 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.support.ColumnCache; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import com.github.yulichang.toolkit.support.ColumnCache; import com.github.yulichang.toolkit.support.SerializedLambda; import org.apache.ibatis.reflection.property.PropertyNamer; @@ -79,15 +79,6 @@ public final class LambdaUtils { return key.toUpperCase(ENGLISH); } - /** - * 将传入的表信息加入缓存 - * - * @param tableInfo 表信息 - */ - @SuppressWarnings("unused") - public static void installCache(TableInfo tableInfo) { - COLUMN_CACHE_MAP.put(tableInfo.getEntityType().getName(), createColumnCacheMap(tableInfo)); - } /** * 缓存实体字段 MAP 信息 @@ -100,13 +91,14 @@ public final class LambdaUtils { if (info.havePK()) { map = CollectionUtils.newHashMapWithExpectedSize(info.getFieldList().size() + 1); - map.put(formatKey(info.getKeyProperty()), new ColumnCache(info.getKeyColumn(), info.getKeySqlSelect())); + map.put(formatKey(info.getKeyProperty()), new ColumnCache(info.getKeyColumn(), info.getKeySqlSelect(), + null, info.getKeyProperty(), true)); } else { map = CollectionUtils.newHashMapWithExpectedSize(info.getFieldList().size()); } info.getFieldList().forEach(i -> - map.put(formatKey(i.getProperty()), new ColumnCache(i.getColumn(), i.getSqlSelect())) + map.put(formatKey(i.getProperty()), new ColumnCache(i.getColumn(), i.getSqlSelect(), i, null, false)) ); return map; } diff --git a/src/main/java/com/github/yulichang/toolkit/CacheList.java b/src/main/java/com/github/yulichang/toolkit/UniqueList.java similarity index 94% rename from src/main/java/com/github/yulichang/toolkit/CacheList.java rename to src/main/java/com/github/yulichang/toolkit/UniqueList.java index e1ab861..03b9d6e 100644 --- a/src/main/java/com/github/yulichang/toolkit/CacheList.java +++ b/src/main/java/com/github/yulichang/toolkit/UniqueList.java @@ -11,7 +11,7 @@ import java.util.Collection; * @author yulichang * @since 1.2.5 */ -public class CacheList extends ArrayList implements UniqueObject { +public class UniqueList extends ArrayList implements UniqueObject { private String uniqueKey; diff --git a/src/main/java/com/github/yulichang/toolkit/support/ColumnCache.java b/src/main/java/com/github/yulichang/toolkit/support/ColumnCache.java new file mode 100644 index 0000000..54b24fa --- /dev/null +++ b/src/main/java/com/github/yulichang/toolkit/support/ColumnCache.java @@ -0,0 +1,41 @@ +package com.github.yulichang.toolkit.support; + +import com.baomidou.mybatisplus.core.metadata.TableFieldInfo; +import lombok.Getter; + +/** + * 缓存添加tableInfo信息 + * + * @author yulichang + * @see com.baomidou.mybatisplus.core.toolkit.support.ColumnCache + * @since 1.2.5 + */ +public class ColumnCache extends com.baomidou.mybatisplus.core.toolkit.support.ColumnCache { + + @Getter + private TableFieldInfo tableFieldInfo; + + @Getter + private String keyProperty; + + @Getter + private boolean isPK; + + + @Deprecated + public ColumnCache(String column, String columnSelect) { + super(column, columnSelect); + } + + @Deprecated + public ColumnCache(String column, String columnSelect, String mapping) { + super(column, columnSelect, mapping); + } + + public ColumnCache(String column, String columnSelect, TableFieldInfo tableFieldInfo, String keyProperty, boolean isPK) { + super(column, columnSelect); + this.tableFieldInfo = tableFieldInfo; + this.keyProperty = keyProperty; + this.isPK = isPK; + } +} diff --git a/src/main/java/com/github/yulichang/wrapper/MPJAbstractLambdaWrapper.java b/src/main/java/com/github/yulichang/wrapper/MPJAbstractLambdaWrapper.java index 9b9ece8..b82eeae 100644 --- a/src/main/java/com/github/yulichang/wrapper/MPJAbstractLambdaWrapper.java +++ b/src/main/java/com/github/yulichang/wrapper/MPJAbstractLambdaWrapper.java @@ -1,10 +1,10 @@ package com.github.yulichang.wrapper; 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.github.yulichang.toolkit.Constant; import com.github.yulichang.toolkit.LambdaUtils; +import com.github.yulichang.toolkit.support.ColumnCache; import java.util.Arrays; import java.util.HashMap; diff --git a/src/main/java/com/github/yulichang/wrapper/MPJLambdaWrapper.java b/src/main/java/com/github/yulichang/wrapper/MPJLambdaWrapper.java index d7422fc..690c1ba 100644 --- a/src/main/java/com/github/yulichang/wrapper/MPJLambdaWrapper.java +++ b/src/main/java/com/github/yulichang/wrapper/MPJLambdaWrapper.java @@ -11,6 +11,7 @@ import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.github.yulichang.toolkit.*; +import com.github.yulichang.toolkit.support.ColumnCache; import com.github.yulichang.wrapper.enums.BaseFuncEnum; import com.github.yulichang.wrapper.interfaces.LambdaJoin; import com.github.yulichang.wrapper.interfaces.Query; @@ -50,7 +51,7 @@ public class MPJLambdaWrapper extends MPJAbstractLambdaWrapper selectColumns = new CacheList<>(); + private final List selectColumns = new UniqueList<>(); /** * ON sql wrapper集合 */ @@ -67,7 +68,7 @@ public class MPJLambdaWrapper extends MPJAbstractLambdaWrapper extends MPJAbstractLambdaWrapper MPJLambdaWrapper select(SFunction... columns) { if (ArrayUtils.isNotEmpty(columns)) { for (SFunction s : columns) { - selectColumns.add(SelectColumn.of(LambdaUtils.getEntityClass(s), getCache(s).getColumn(), null)); + ColumnCache cache = getCache(s); + selectColumns.add(SelectColumn.of(LambdaUtils.getEntityClass(s), cache.getColumn(), cache.getTableFieldInfo(), + null, cache.getTableFieldInfo() == null ? cache.getKeyProperty() : cache.getTableFieldInfo().getProperty(), null)); } } return typedThis; @@ -139,7 +142,7 @@ public class MPJLambdaWrapper extends MPJAbstractLambdaWrapper selectColumns.add(SelectColumn.of(entityClass, i.getColumn(), i))); + i -> selectColumns.add(SelectColumn.of(entityClass, i.getColumn(), i, null, i.getProperty(), null))); return typedThis; } @@ -150,24 +153,26 @@ public class MPJLambdaWrapper extends MPJAbstractLambdaWrapper tagFields = ReflectionKit.getFieldList(tag); tableInfo.getFieldList().forEach(i -> { if (tagFields.stream().anyMatch(f -> f.getName().equals(i.getProperty()))) { - selectColumns.add(SelectColumn.of(source, i.getColumn(), i)); + selectColumns.add(SelectColumn.of(source, i.getColumn(), i, null, i.getProperty(), null)); } }); if (tableInfo.havePK() && tagFields.stream().anyMatch(i -> i.getName().equals(tableInfo.getKeyProperty()))) { - selectColumns.add(SelectColumn.of(source, tableInfo.getKeyColumn(), null)); + selectColumns.add(SelectColumn.of(source, tableInfo.getKeyColumn(), null, null, tableInfo.getKeyProperty(), null)); } return typedThis; } @Override public MPJLambdaWrapper selectAs(SFunction column, String alias) { - selectColumns.add(SelectColumn.of(LambdaUtils.getEntityClass(column), getCache(column).getColumn(), null, alias)); + ColumnCache cache = getCache(column); + selectColumns.add(SelectColumn.of(LambdaUtils.getEntityClass(column), cache.getColumn(), cache.getTableFieldInfo(), alias, null, null)); return typedThis; } public MPJLambdaWrapper selectFunc(boolean condition, BaseFuncEnum funcEnum, SFunction column, String alias) { if (condition) { - selectColumns.add(SelectColumn.of(LambdaUtils.getEntityClass(column), getCache(column).getColumn(), null, alias, funcEnum)); + ColumnCache cache = getCache(column); + selectColumns.add(SelectColumn.of(LambdaUtils.getEntityClass(column), cache.getColumn(), cache.getTableFieldInfo(), alias, alias, funcEnum)); } return typedThis; } @@ -175,7 +180,7 @@ public class MPJLambdaWrapper extends MPJAbstractLambdaWrapper selectFunc(boolean condition, BaseFuncEnum funcEnum, Object column, String alias) { if (condition) { - selectColumns.add(SelectColumn.of(null, column.toString(), null, alias, funcEnum)); + selectColumns.add(SelectColumn.of(null, column.toString(), null, alias, alias, funcEnum)); } return typedThis; } @@ -184,10 +189,10 @@ public class MPJLambdaWrapper extends MPJAbstractLambdaWrapper %s", clazz); if (info.havePK()) { - selectColumns.add(SelectColumn.of(clazz, info.getKeyColumn(), null)); + selectColumns.add(SelectColumn.of(clazz, info.getKeyColumn(), null, null, info.getKeyProperty(), null)); } info.getFieldList().forEach(c -> - selectColumns.add(SelectColumn.of(clazz, c.getColumn(), c))); + selectColumns.add(SelectColumn.of(clazz, c.getColumn(), c, null, c.getProperty(), null))); return typedThis; } diff --git a/src/main/java/com/github/yulichang/wrapper/SelectColumn.java b/src/main/java/com/github/yulichang/wrapper/SelectColumn.java index 4db4ef5..0451b7f 100644 --- a/src/main/java/com/github/yulichang/wrapper/SelectColumn.java +++ b/src/main/java/com/github/yulichang/wrapper/SelectColumn.java @@ -2,6 +2,7 @@ package com.github.yulichang.wrapper; import com.baomidou.mybatisplus.core.metadata.TableFieldInfo; import com.baomidou.mybatisplus.core.toolkit.StringPool; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.github.yulichang.toolkit.UniqueObject; import com.github.yulichang.wrapper.enums.BaseFuncEnum; import lombok.Data; @@ -37,30 +38,30 @@ public class SelectColumn implements UniqueObject { */ private String alias; + /** + * 目标属性 + */ + private String tagProperty; + /** * 字段函数 */ private BaseFuncEnum funcEnum; - private SelectColumn(Class clazz, String columnName, TableFieldInfo tableFieldInfo, String alias, BaseFuncEnum funcEnum) { + private SelectColumn(Class clazz, String columnName, TableFieldInfo tableFieldInfo, String alias, String tagProperty, BaseFuncEnum funcEnum) { this.clazz = clazz; this.columnName = columnName; this.tableFieldInfo = tableFieldInfo; this.alias = alias; + this.tagProperty = tagProperty; this.funcEnum = funcEnum; } - public static SelectColumn of(Class clazz, String columnName, TableFieldInfo tableFieldInfo) { - return new SelectColumn(clazz, columnName, tableFieldInfo, null, null); - } - - public static SelectColumn of(Class clazz, String columnName, TableFieldInfo tableFieldInfo, String alias) { - return new SelectColumn(clazz, columnName, tableFieldInfo, alias, null); - } - - public static SelectColumn of(Class clazz, String columnName, TableFieldInfo tableFieldInfo, String alias, BaseFuncEnum funcEnum) { - return new SelectColumn(clazz, columnName, tableFieldInfo, alias, funcEnum); + public static SelectColumn of(Class clazz, String columnName, TableFieldInfo tableFieldInfo, String alias, String tagProperty, BaseFuncEnum funcEnum) { + if (tagProperty != null) + tagProperty = StringUtils.getTargetColumn(tagProperty); + return new SelectColumn(clazz, columnName, tableFieldInfo, alias, tagProperty, funcEnum); } /**