From f230f52b44b5ee355381cb3fa33fb9c559f56651 Mon Sep 17 00:00:00 2001 From: admin <570810310@qq.com> Date: Fri, 21 May 2021 17:15:22 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8D=87=E7=BA=A7mybatis-plus=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E5=88=B0=203.4.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yulichang/interceptor/MPJInterceptor.java | 56 ++- .../yulichang/metadata/TableFieldInfo.java | 406 ------------------ .../github/yulichang/metadata/TableInfo.java | 234 ---------- .../yulichang/metadata/TableInfoHelper.java | 363 ---------------- .../github/yulichang/toolkit/LambdaUtils.java | 48 ++- .../yulichang/toolkit/sql/SqlScriptUtils.java | 221 ++++++++++ .../toolkit/support/SerializedLambda.java | 128 ++++++ .../yulichang/wrapper/MPJAbstractWrapper.java | 2 +- 8 files changed, 427 insertions(+), 1031 deletions(-) delete mode 100644 src/main/java/com/github/yulichang/metadata/TableFieldInfo.java delete mode 100644 src/main/java/com/github/yulichang/metadata/TableInfo.java delete mode 100644 src/main/java/com/github/yulichang/metadata/TableInfoHelper.java create mode 100644 src/main/java/com/github/yulichang/toolkit/sql/SqlScriptUtils.java create mode 100644 src/main/java/com/github/yulichang/toolkit/support/SerializedLambda.java diff --git a/src/main/java/com/github/yulichang/interceptor/MPJInterceptor.java b/src/main/java/com/github/yulichang/interceptor/MPJInterceptor.java index a097384..6362849 100644 --- a/src/main/java/com/github/yulichang/interceptor/MPJInterceptor.java +++ b/src/main/java/com/github/yulichang/interceptor/MPJInterceptor.java @@ -1,9 +1,11 @@ package com.github.yulichang.interceptor; +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.StringPool; -import com.github.yulichang.metadata.TableInfo; -import com.github.yulichang.metadata.TableInfoHelper; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.github.yulichang.method.MPJResultType; import com.github.yulichang.toolkit.Constant; import org.apache.ibatis.executor.Executor; @@ -15,9 +17,16 @@ import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.plugin.Intercepts; import org.apache.ibatis.plugin.Invocation; import org.apache.ibatis.plugin.Signature; +import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.RowBounds; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.TypeHandler; +import org.apache.ibatis.type.TypeHandlerRegistry; +import org.apache.ibatis.type.UnknownTypeHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -105,12 +114,22 @@ public class MPJInterceptor implements Interceptor { * 构建resultMap */ private ResultMap newResultMap(MappedStatement ms, Class> resultType) { - com.baomidou.mybatisplus.core.metadata.TableInfo tableInfo = com.baomidou.mybatisplus.core.metadata.TableInfoHelper.getTableInfo(resultType); + TableInfo tableInfo = TableInfoHelper.getTableInfo(resultType); if (tableInfo != null && tableInfo.isAutoInitResultMap()) { ResultMap resultMap = RM_CACHE.get(resultType); if (resultMap == null) { - TableInfo info = TableInfoHelper.initTableInfo(ms.getConfiguration(), ms.getId().substring(0, ms.getId().lastIndexOf(".")), resultType); - resultMap = initResultMapIfNeed(info, resultType); + if (tableInfo.getEntityType() != resultType) { + try { + Method info = TableInfoHelper.class.getDeclaredMethod("initTableInfo", Configuration.class, String.class, Class.class); + info.setAccessible(true); + Object invoke = info.invoke(TableInfoHelper.class, ms.getConfiguration(), ms.getId().substring(0, ms.getId().lastIndexOf(".")), resultType); + tableInfo = (TableInfo) invoke; +// tableInfo = TableInfoHelper.initTableInfo(ms.getConfiguration(), ms.getId().substring(0, ms.getId().lastIndexOf(".")), resultType); + } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { + e.printStackTrace(); + } + } + resultMap = initResultMapIfNeed(tableInfo, resultType); RM_CACHE.put(resultType, resultMap); } return resultMap; @@ -130,8 +149,33 @@ public class MPJInterceptor implements Interceptor { resultMappings.add(idMapping); } if (CollectionUtils.isNotEmpty(info.getFieldList())) { - info.getFieldList().forEach(i -> resultMappings.add(i.getResultMapping(info.getConfiguration()))); + info.getFieldList().forEach(i -> resultMappings.add(getResultMapping(i, info.getConfiguration()))); } return new ResultMap.Builder(info.getConfiguration(), id, resultType, resultMappings).build(); } + + + /** + * 获取 ResultMapping + * + * @param configuration MybatisConfiguration + * @return ResultMapping + */ + private ResultMapping getResultMapping(TableFieldInfo info, final Configuration configuration) { + ResultMapping.Builder builder = new ResultMapping.Builder(configuration, info.getProperty(), + StringUtils.getTargetColumn(info.getColumn()), info.getPropertyType()); + TypeHandlerRegistry registry = configuration.getTypeHandlerRegistry(); + if (info.getJdbcType() != null && info.getJdbcType() != JdbcType.UNDEFINED) { + builder.jdbcType(info.getJdbcType()); + } + if (info.getTypeHandler() != null && info.getTypeHandler() != UnknownTypeHandler.class) { + TypeHandler> typeHandler = registry.getMappingTypeHandler(info.getTypeHandler()); + if (typeHandler == null) { + typeHandler = registry.getInstance(info.getPropertyType(), info.getTypeHandler()); + // todo 这会有影响 registry.register(typeHandler); + } + builder.typeHandler(typeHandler); + } + return builder.build(); + } } diff --git a/src/main/java/com/github/yulichang/metadata/TableFieldInfo.java b/src/main/java/com/github/yulichang/metadata/TableFieldInfo.java deleted file mode 100644 index a6d26f5..0000000 --- a/src/main/java/com/github/yulichang/metadata/TableFieldInfo.java +++ /dev/null @@ -1,406 +0,0 @@ -package com.github.yulichang.metadata; - -import com.baomidou.mybatisplus.annotation.*; -import com.baomidou.mybatisplus.core.config.GlobalConfig; -import com.baomidou.mybatisplus.core.toolkit.Constants; -import com.baomidou.mybatisplus.core.toolkit.StringUtils; -import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils; -import lombok.*; -import org.apache.ibatis.mapping.ResultMapping; -import org.apache.ibatis.reflection.Reflector; -import org.apache.ibatis.session.Configuration; -import org.apache.ibatis.type.*; - -import java.lang.reflect.Field; -import java.util.Map; - -/** - * 为自定义resultType提供resultMap - *
- * copy {@link com.baomidou.mybatisplus.core.metadata.TableFieldInfo} - */ -@Getter -@ToString -@EqualsAndHashCode -@SuppressWarnings("serial") -public class TableFieldInfo implements Constants { - - /** - * 属性 - * - * @since 3.3.1 - */ - private final Field field; - /** - * 字段名 - */ - private final String column; - /** - * 属性名 - */ - private final String property; - /** - * 属性表达式#{property}, 可以指定jdbcType, typeHandler等 - */ - private final String el; - /** - * jdbcType, typeHandler等部分 - */ - private final String mapping; - /** - * 属性类型 - */ - private final Class> propertyType; - /** - * 是否是基本数据类型 - * - * @since 3.4.0 @2020-6-19 - */ - private final boolean isPrimitive; - /** - * 属性是否是 CharSequence 类型 - */ - private final boolean isCharSequence; - /** - * 字段验证策略之 insert - * Refer to {@link TableField#insertStrategy()} - * - * @since added v_3.1.2 @2019-5-7 - */ - private final FieldStrategy insertStrategy; - /** - * 字段验证策略之 update - * Refer to {@link TableField#updateStrategy()} - * - * @since added v_3.1.2 @2019-5-7 - */ - private final FieldStrategy updateStrategy; - /** - * 字段验证策略之 where - * Refer to {@link TableField#whereStrategy()} - * - * @since added v_3.1.2 @2019-5-7 - */ - private final FieldStrategy whereStrategy; - /** - * 是否是乐观锁字段 - */ - private final boolean version; - /** - * 是否进行 select 查询 - *
大字段可设置为 false 不加入 select 查询范围
- */ - private boolean select = true; - /** - * 是否是逻辑删除字段 - */ - private boolean logicDelete = false; - /** - * 逻辑删除值 - */ - private String logicDeleteValue; - /** - * 逻辑未删除值 - */ - private String logicNotDeleteValue; - /** - * 字段 update set 部分注入 - */ - private String update; - /** - * where 字段比较条件 - */ - private String condition = SqlCondition.EQUAL; - /** - * 字段填充策略 - */ - private FieldFill fieldFill = FieldFill.DEFAULT; - /** - * 表字段是否启用了插入填充 - * - * @since 3.3.0 - */ - private boolean withInsertFill; - /** - * 表字段是否启用了更新填充 - * - * @since 3.3.0 - */ - private boolean withUpdateFill; - /** - * 缓存 sql select - */ - @Setter(AccessLevel.NONE) - private String sqlSelect; - /** - * JDBC类型 - * - * @since 3.1.2 - */ - private JdbcType jdbcType; - /** - * 类型处理器 - * - * @since 3.1.2 - */ - private Class extends TypeHandler>> typeHandler; - - /** - * 是否存在OrderBy注解 - */ - private boolean isOrderBy; - /** - * 排序类型 - */ - private String orderByType; - /** - * 排序顺序 - */ - private short orderBySort; - - /** - * 全新的 存在 TableField 注解时使用的构造函数 - */ - @SuppressWarnings({"unchecked", "rawtypes"}) - public TableFieldInfo(GlobalConfig.DbConfig dbConfig, TableInfo tableInfo, Field field, TableField tableField, - Reflector reflector, boolean existTableLogic,boolean isOrderBy) { - this(dbConfig,tableInfo,field,tableField,reflector,existTableLogic); - this.isOrderBy = isOrderBy; - if(isOrderBy){ - initOrderBy(field); - } - } - - /** - * 全新的 存在 TableField 注解时使用的构造函数 - */ - @SuppressWarnings({"unchecked", "rawtypes"}) - public TableFieldInfo(GlobalConfig.DbConfig dbConfig, TableInfo tableInfo, Field field, TableField tableField, - Reflector reflector, boolean existTableLogic) { - field.setAccessible(true); - this.field = field; - this.version = field.getAnnotation(Version.class) != null; - this.property = field.getName(); - this.propertyType = reflector.getGetterType(this.property); - this.isPrimitive = this.propertyType.isPrimitive(); - this.isCharSequence = StringUtils.isCharSequence(this.propertyType); - this.fieldFill = tableField.fill(); - this.withInsertFill = this.fieldFill == FieldFill.INSERT || this.fieldFill == FieldFill.INSERT_UPDATE; - this.withUpdateFill = this.fieldFill == FieldFill.UPDATE || this.fieldFill == FieldFill.INSERT_UPDATE; - this.update = tableField.update(); - JdbcType jdbcType = tableField.jdbcType(); - final Class extends TypeHandler> typeHandler = tableField.typeHandler(); - final String numericScale = tableField.numericScale(); - String el = this.property; - if (JdbcType.UNDEFINED != jdbcType) { - this.jdbcType = jdbcType; - el += (COMMA + SqlScriptUtils.mappingJdbcType(jdbcType)); - } - if (UnknownTypeHandler.class != typeHandler) { - this.typeHandler = (Class extends TypeHandler>>) typeHandler; - if (tableField.javaType()) { - String javaType = null; - TypeAliasRegistry registry = tableInfo.getConfiguration().getTypeAliasRegistry(); - Map- * copy {@link com.baomidou.mybatisplus.core.metadata.TableInfo} - */ -@Data -@Setter(AccessLevel.PACKAGE) -@Accessors(chain = true) -@SuppressWarnings("serial") -public class TableInfo implements Constants { - - /** - * 实体类型 - */ - private Class> entityType; - /** - * 表主键ID 类型 - */ - private IdType idType = IdType.NONE; - /** - * 表名称 - */ - private String tableName; - /** - * 表映射结果集 - */ - private String resultMap; - /** - * 是否是需要自动生成的 resultMap - */ - private boolean autoInitResultMap; - /** - * 主键是否有存在字段名与属性名关联 - *
true: 表示要进行 as
- */ - private boolean keyRelated; - /** - * 表主键ID 字段名 - */ - private String keyColumn; - /** - * 表主键ID 属性名 - */ - private String keyProperty; - /** - * 表主键ID 属性类型 - */ - private Class> keyType; - /** - * 表主键ID Sequence - */ - private KeySequence keySequence; - /** - * 表字段信息列表 - */ - private List
- * 未注解指定字段名的情况下,用于自动从 property 推算 column 的命名
- */
- private boolean underCamel;
- /**
- * 缓存包含主键及字段的 sql select
- */
- @Setter(AccessLevel.NONE)
- @Getter(AccessLevel.NONE)
- private String allSqlSelect;
- /**
- * 缓存主键字段的 sql select
- */
- @Setter(AccessLevel.NONE)
- @Getter(AccessLevel.NONE)
- private String sqlSelect;
- /**
- * 表字段是否启用了插入填充
- *
- * @since 3.3.0
- */
- @Getter
- @Setter(AccessLevel.NONE)
- private boolean withInsertFill;
- /**
- * 表字段是否启用了更新填充
- *
- * @since 3.3.0
- */
- @Getter
- @Setter(AccessLevel.NONE)
- private boolean withUpdateFill;
- /**
- * 表字段是否启用了逻辑删除
- *
- * @since 3.4.0
- */
- @Getter
- @Setter(AccessLevel.NONE)
- private boolean withLogicDelete;
- /**
- * 逻辑删除字段
- *
- * @since 3.4.0
- */
- @Getter
- @Setter(AccessLevel.NONE)
- private TableFieldInfo logicDeleteFieldInfo;
- /**
- * 表字段是否启用了乐观锁
- *
- * @since 3.3.1
- */
- @Getter
- @Setter(AccessLevel.NONE)
- private boolean withVersion;
- /**
- * 乐观锁字段
- *
- * @since 3.3.1
- */
- @Getter
- @Setter(AccessLevel.NONE)
- private TableFieldInfo versionFieldInfo;
-
- /**
- * 排序列表
- */
- @Getter
- @Setter
- public List
- * copy {@link com.baomidou.mybatisplus.core.metadata.TableInfoHelper}
- */
-public class TableInfoHelper {
-
- private static final Log logger = LogFactory.getLog(TableInfoHelper.class);
-
- /**
- * 默认表主键名称
- */
- private static final String DEFAULT_ID_NAME = "id";
-
- public synchronized static TableInfo initTableInfo(Configuration configuration, String currentNamespace, Class> clazz) {
- /* 没有获取到缓存信息,则初始化 */
- TableInfo tableInfo = new TableInfo(clazz);
- tableInfo.setCurrentNamespace(currentNamespace);
- tableInfo.setConfiguration(configuration);
- GlobalConfig globalConfig = GlobalConfigUtils.getGlobalConfig(configuration);
- /* 初始化表名相关 */
- final String[] excludeProperty = initTableName(clazz, globalConfig, tableInfo);
- List
- * 初始化 表数据库类型,表名,resultMap
- *
- * 初始化 表主键,表字段
- *
- * 判断主键注解是否存在
- *
- * 判断逻辑删除注解是否存在
- *
- * 判断排序注解是否存在
- *
- * 主键属性初始化
- *
- * 主键属性初始化
- *
- * 为 true 表示不符合规则
- *
- * @param underCamel 驼峰命名
- * @param property 属性名
- * @param column 字段名
- * @return related
- */
- public static boolean checkRelated(boolean underCamel, String property, String column) {
- column = StringUtils.getTargetColumn(column);
- String propertyUpper = property.toUpperCase(Locale.ENGLISH);
- String columnUpper = column.toUpperCase(Locale.ENGLISH);
- if (underCamel) {
- // 开启了驼峰并且 column 包含下划线
- return !(propertyUpper.equals(columnUpper) ||
- propertyUpper.equals(columnUpper.replace(StringPool.UNDERSCORE, StringPool.EMPTY)));
- } else {
- // 未开启驼峰,直接判断 property 是否与 column 相同(全大写)
- return !propertyUpper.equals(columnUpper);
- }
- }
-
- /**
- *
- * 获取该类的所有属性列表
- *
+ * sql 脚本工具类
+ *
+ * 获取 带 if 标签的脚本
+ *
+ * 获取 带 trim 标签的脚本
+ *
+ * 生成 choose 标签的脚本
+ *
+ * 生成 foreach 标签的脚本
+ *
+ * 生成 where 标签的脚本
+ *
+ * 生成 set 标签的脚本
+ *
+ * 安全入参: #{入参}
+ *
+ * 安全入参: #{入参,mapping}
+ *
+ * 非安全入参: ${入参}
+ * 负责将一个支持序列的 Function 序列化为 SerializedLambda