From f020d64af34c046befd9de292b5ba1cc6823b0e4 Mon Sep 17 00:00:00 2001 From: yulichang <570810310@qq.com> Date: Fri, 4 Nov 2022 17:26:51 +0800 Subject: [PATCH] =?UTF-8?q?1.2.5=E7=89=88=E6=9C=AC=E4=B8=B4=E6=97=B6?= =?UTF-8?q?=E5=88=86=E6=94=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yulichang/config/InterceptorConfig.java | 2 +- .../github/yulichang/toolkit/BiHashMap.java | 28 ++++++ .../yulichang/toolkit/ReflectionKit.java | 25 +++++- .../yulichang/wrapper/MPJLambdaWrapper.java | 67 +++++++++++++-- .../wrapper/resultmap/Collection.java | 84 ++++++++++++++++++ .../yulichang/wrapper/resultmap/MFunc.java | 7 ++ .../wrapper/resultmap/MPJResultMap.java | 12 +++ .../yulichang/wrapper/resultmap/Result.java | 85 +++++++++++++++++++ 8 files changed, 299 insertions(+), 11 deletions(-) create mode 100644 src/main/java/com/github/yulichang/toolkit/BiHashMap.java create mode 100644 src/main/java/com/github/yulichang/wrapper/resultmap/Collection.java create mode 100644 src/main/java/com/github/yulichang/wrapper/resultmap/MFunc.java create mode 100644 src/main/java/com/github/yulichang/wrapper/resultmap/MPJResultMap.java create mode 100644 src/main/java/com/github/yulichang/wrapper/resultmap/Result.java diff --git a/src/main/java/com/github/yulichang/config/InterceptorConfig.java b/src/main/java/com/github/yulichang/config/InterceptorConfig.java index a69b60e..882fb70 100644 --- a/src/main/java/com/github/yulichang/config/InterceptorConfig.java +++ b/src/main/java/com/github/yulichang/config/InterceptorConfig.java @@ -25,7 +25,7 @@ import java.util.Objects; * * @author yulichang */ -@SuppressWarnings("SpringJavaAutowiredMembersInspection") +@SuppressWarnings("NullableProblems") public class InterceptorConfig implements ApplicationListener { private static final Log logger = LogFactory.getLog(InterceptorConfig.class); diff --git a/src/main/java/com/github/yulichang/toolkit/BiHashMap.java b/src/main/java/com/github/yulichang/toolkit/BiHashMap.java new file mode 100644 index 0000000..83969c4 --- /dev/null +++ b/src/main/java/com/github/yulichang/toolkit/BiHashMap.java @@ -0,0 +1,28 @@ +package com.github.yulichang.toolkit; + +import java.util.HashMap; +import java.util.Map; + +public class BiHashMap { + + private final Map> map; + + public BiHashMap() { + this.map = new HashMap<>(); + } + + + public E get(K k, V v) { + return map.containsKey(k) ? map.get(k).get(v) : null; + } + + public void put(K k, V v, E e) { + if (map.containsKey(k)) { + map.get(k).put(v, e); + } else { + Map veMap = new HashMap<>(); + veMap.put(v, e); + map.put(k, veMap); + } + } +} diff --git a/src/main/java/com/github/yulichang/toolkit/ReflectionKit.java b/src/main/java/com/github/yulichang/toolkit/ReflectionKit.java index 27c14be..e7b663d 100644 --- a/src/main/java/com/github/yulichang/toolkit/ReflectionKit.java +++ b/src/main/java/com/github/yulichang/toolkit/ReflectionKit.java @@ -23,8 +23,7 @@ import org.apache.ibatis.logging.Log; import org.apache.ibatis.logging.LogFactory; import org.springframework.core.GenericTypeResolver; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; +import java.lang.reflect.*; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @@ -101,6 +100,28 @@ public final class ReflectionKit { return null == typeArguments ? null : typeArguments[index]; } + + /** + * Collection字段的泛型 + */ + public static Class getGenericType(Field field) { + Type type = field.getGenericType(); + //没有写泛型 + if (!(type instanceof ParameterizedType)) { + return Object.class; + } + ParameterizedType pt = (ParameterizedType) type; + Type[] actualTypeArguments = pt.getActualTypeArguments(); + Type argument = actualTypeArguments[0]; + //通配符泛型 ? , ? extends XXX , ? super XXX + if (argument instanceof WildcardType) { + //获取上界 + Type[] types = ((WildcardType) argument).getUpperBounds(); + return (Class) types[0]; + } + return (Class) argument; + } + /** *

* 获取该类的所有属性列表 diff --git a/src/main/java/com/github/yulichang/wrapper/MPJLambdaWrapper.java b/src/main/java/com/github/yulichang/wrapper/MPJLambdaWrapper.java index 923ee01..05b3fac 100644 --- a/src/main/java/com/github/yulichang/wrapper/MPJLambdaWrapper.java +++ b/src/main/java/com/github/yulichang/wrapper/MPJLambdaWrapper.java @@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.core.toolkit.Assert; 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.exception.MPJException; import com.github.yulichang.toolkit.*; import com.github.yulichang.toolkit.support.ColumnCache; import com.github.yulichang.toolkit.support.SelectColumn; @@ -17,6 +18,8 @@ import com.github.yulichang.wrapper.enums.BaseFuncEnum; import com.github.yulichang.wrapper.interfaces.LambdaJoin; import com.github.yulichang.wrapper.interfaces.Query; import com.github.yulichang.wrapper.interfaces.on.OnFunction; +import com.github.yulichang.wrapper.resultmap.Collection; +import com.github.yulichang.wrapper.resultmap.MFunc; import lombok.Getter; import java.lang.reflect.Field; @@ -36,7 +39,7 @@ import java.util.stream.Collectors; * @author yulichang * @see MPJWrappers */ -@SuppressWarnings("unused") +@SuppressWarnings({"unused", "unchecked"}) public class MPJLambdaWrapper extends MPJAbstractLambdaWrapper> implements Query>, LambdaJoin, T> { @@ -57,6 +60,16 @@ public class MPJLambdaWrapper extends MPJAbstractLambdaWrapper> onWrappers = new ArrayList<>(); + /** + * 敌对多映射关系 + */ + @Getter + private final List> resultMapCollection = new ArrayList<>(); + /** + * 是否构建是否存在一对多 + */ + @Getter + private boolean resultMap = false; /** * 查询字段 sql */ @@ -65,11 +78,6 @@ public class MPJLambdaWrapper extends MPJAbstractLambdaWrapper extends MPJAbstractLambdaWrapper> MPJLambdaWrapper selectCollection(Class child, SFunction dtoField) { + String dtoFieldName = LambdaUtils.getName(dtoField); + Class dtoClass = LambdaUtils.getEntityClass(dtoField); + Map fieldMap = ReflectionKit.getFieldMap(dtoClass); + Field field = fieldMap.get(dtoFieldName); + this.resultMap = true; + Class genericType = ReflectionKit.getGenericType(field); + Collection.Builder builder; + if (genericType == null || genericType.isAssignableFrom(child)) { + //找不到集合泛型 List List List , 直接查询数据库实体 + builder = new Collection.Builder<>(dtoFieldName, child, field.getType()); + } else { + Class ofType = (Class) genericType; + if (ReflectionKit.isPrimitiveOrWrapper(ofType) || fieldMap.isEmpty()) { + throw new MPJException("collection 不支持基本数据类型"); + } + builder = new Collection.Builder<>(dtoFieldName, child, field.getType(), ofType); + } + this.resultMapCollection.add(builder.build()); + return typedThis; + } + + public > MPJLambdaWrapper + selectCollection(Class child, SFunction dtoField, MFunc> collection) { + String dtoFieldName = LambdaUtils.getName(dtoField); + Class dtoClass = LambdaUtils.getEntityClass(dtoField); + Field field = ReflectionKit.getFieldMap(dtoClass).get(dtoFieldName); + this.resultMap = true; + //获取集合泛型 + Class genericType = ReflectionKit.getGenericType(field); + Class ofType = (Class) genericType; + Collection.Builder builder = new Collection.Builder<>(dtoFieldName, child, field.getType(), ofType); + this.resultMapCollection.add(collection.apply(builder).build()); + return typedThis; + } + + public MPJLambdaWrapper selectAssociation(Class child, SFunction dtoField, MFunc> collection) { + //TODO + return typedThis; + } + + @Override public MPJLambdaWrapper select(Class entityClass, Predicate predicate) { TableInfo info = TableInfoHelper.getTableInfo(entityClass); - Assert.notNull(info, "table can not be find"); + Assert.notNull(info, "table not find by class <%s>", entityClass.getName()); info.getFieldList().stream().filter(predicate).collect(Collectors.toList()).forEach( i -> selectColumns.add(SelectColumn.of(entityClass, i.getColumn(), i, null, i.getProperty(), null))); return typedThis; @@ -150,7 +201,7 @@ public class MPJLambdaWrapper extends MPJAbstractLambdaWrapper MPJLambdaWrapper selectAsClass(Class source, Class tag) { TableInfo tableInfo = TableInfoHelper.getTableInfo(source); - Assert.notNull(tableInfo, "table can not be find"); + Assert.notNull(tableInfo, "table not find by class <%s>", source.getName()); List tagFields = ReflectionKit.getFieldList(tag); tableInfo.getFieldList().forEach(i -> { if (tagFields.stream().anyMatch(f -> f.getName().equals(i.getProperty()))) { diff --git a/src/main/java/com/github/yulichang/wrapper/resultmap/Collection.java b/src/main/java/com/github/yulichang/wrapper/resultmap/Collection.java new file mode 100644 index 0000000..3f22600 --- /dev/null +++ b/src/main/java/com/github/yulichang/wrapper/resultmap/Collection.java @@ -0,0 +1,84 @@ +package com.github.yulichang.wrapper.resultmap; + +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +/** + * collection 标签 目前先支持这几个属性 后续在扩展 + * + * @author yulichang + * @since 1.2.5 + */ +@Getter +public class Collection { + + private String property; + + private Class entityClass; + + private Class javaType; + + private Class ofType; + + private List resultList; + + //collection嵌套 +// private List collectionList; + + private Collection() { + } + + public static class Builder { + + private final Collection collection; + + /** + * 自动构建 + */ + @SuppressWarnings("unchecked") + public Builder(String property, Class entityClass, Class javaType) { + this.collection = new Collection<>(); + collection.property = property; + collection.entityClass = entityClass; + collection.javaType = javaType; + collection.ofType = (Class) entityClass; + collection.resultList = new ArrayList<>(); + // TODO 构建entityClass所有的字段 + } + + /** + * 手动构建 + * + * @param property property + * @param entityClass 数据库实体类 + * @param javaType javaType + * @param ofType 映射类 + */ + public Builder(String property, Class entityClass, Class javaType, Class ofType) { + this.collection = new Collection<>(); + collection.property = property; + collection.entityClass = entityClass; + collection.javaType = javaType; + collection.ofType = ofType; + collection.resultList = new ArrayList<>(); + } + + public Builder id(MFunc> result) { + Result r = result.apply(new Result.Builder<>(true)).build(); + collection.resultList.add(r); + return this; + } + + public Builder result(MFunc> result) { + Result r = result.apply(new Result.Builder<>(false)).build(); + collection.resultList.add(r); + return this; + } + + public Collection build() { + return collection; + } + } +} diff --git a/src/main/java/com/github/yulichang/wrapper/resultmap/MFunc.java b/src/main/java/com/github/yulichang/wrapper/resultmap/MFunc.java new file mode 100644 index 0000000..f9bf531 --- /dev/null +++ b/src/main/java/com/github/yulichang/wrapper/resultmap/MFunc.java @@ -0,0 +1,7 @@ +package com.github.yulichang.wrapper.resultmap; + +@FunctionalInterface +public interface MFunc { + + T apply(T t); +} diff --git a/src/main/java/com/github/yulichang/wrapper/resultmap/MPJResultMap.java b/src/main/java/com/github/yulichang/wrapper/resultmap/MPJResultMap.java new file mode 100644 index 0000000..e792eb8 --- /dev/null +++ b/src/main/java/com/github/yulichang/wrapper/resultmap/MPJResultMap.java @@ -0,0 +1,12 @@ +package com.github.yulichang.wrapper.resultmap; + +import lombok.Getter; +import org.apache.ibatis.mapping.ResultMap; + +public class MPJResultMap { + + @Getter + private ResultMap resultMap; + + +} diff --git a/src/main/java/com/github/yulichang/wrapper/resultmap/Result.java b/src/main/java/com/github/yulichang/wrapper/resultmap/Result.java new file mode 100644 index 0000000..d67cd9d --- /dev/null +++ b/src/main/java/com/github/yulichang/wrapper/resultmap/Result.java @@ -0,0 +1,85 @@ +package com.github.yulichang.wrapper.resultmap; + +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.Assert; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import com.github.yulichang.toolkit.LambdaUtils; +import lombok.Getter; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.TypeHandler; + +/** + * result 标签 + * + * @author yulichang + * @since 1.2.5 + */ +@Getter +public class Result { + + private boolean isId; + + private String property; + + private String column; + + private TableFieldInfo tableFieldInfo; + + private Class javaType; + + private JdbcType jdbcType; + + private TypeHandler typeHandle; + + private Result() { + } + + public static class Builder { + + private final Result result; + + public Builder(boolean isId) { + this.result = new Result(); + result.isId = isId; + } + + public Builder property(SFunction property) { + result.property = LambdaUtils.getName(property); + return this; + } + + public Builder column(SFunction column) { + Class entityClass = LambdaUtils.getEntityClass(column); + String name = LambdaUtils.getName(column); + TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass); + Assert.notNull(tableInfo, "table not find by class <%s>", tableInfo); + if (tableInfo.havePK() && tableInfo.getKeyProperty().equals(name)) { + result.column = tableInfo.getKeyColumn(); + } else { + TableFieldInfo fieldInfo = tableInfo.getFieldList().stream().filter(i -> i.getField().getName().equals(name)).findFirst().orElse(null); + Assert.notNull(fieldInfo, "table <%s> not find column <%>", tableInfo.getTableName(), name); + result.column = fieldInfo.getColumn(); + result.tableFieldInfo = fieldInfo; + } + return this; + } + + public Builder javaType(Class javaType) { + result.javaType = javaType; + return this; + } + + public Builder jdbcType(JdbcType jdbcType) { + result.jdbcType = jdbcType; + return this; + } + + public Result build() { + //TODO 检查数据完整性 + return result; + } + + } +}