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> 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 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>) typeHandler; - if (tableField.javaType()) { - String javaType = null; - TypeAliasRegistry registry = tableInfo.getConfiguration().getTypeAliasRegistry(); - Map> typeAliases = registry.getTypeAliases(); - for (Map.Entry> entry : typeAliases.entrySet()) { - if (entry.getValue().equals(propertyType)) { - javaType = entry.getKey(); - break; - } - } - if (javaType == null) { - javaType = propertyType.getName(); - registry.registerAlias(javaType, propertyType); - } - el += (COMMA + "javaType=" + javaType); - } - el += (COMMA + SqlScriptUtils.mappingTypeHandler(this.typeHandler)); - } - if (StringUtils.isNotBlank(numericScale)) { - el += (COMMA + SqlScriptUtils.mappingNumericScale(Integer.valueOf(numericScale))); - } - this.el = el; - int index = el.indexOf(COMMA); - this.mapping = index > 0 ? el.substring(++index) : null; - this.initLogicDelete(dbConfig, field, existTableLogic); - - String column = tableField.value(); - if (StringUtils.isBlank(column)) { - column = this.property; - if (tableInfo.isUnderCamel()) { - /* 开启字段下划线申明 */ - column = StringUtils.camelToUnderline(column); - } - if (dbConfig.isCapitalMode()) { - /* 开启字段全大写申明 */ - column = column.toUpperCase(); - } - } - String columnFormat = dbConfig.getColumnFormat(); - if (StringUtils.isNotBlank(columnFormat) && tableField.keepGlobalFormat()) { - column = String.format(columnFormat, column); - } - - this.column = column; - this.sqlSelect = column; - if (tableInfo.getResultMap() == null && !tableInfo.isAutoInitResultMap() && - TableInfoHelper.checkRelated(tableInfo.isUnderCamel(), this.property, this.column)) { - /* 未设置 resultMap 也未开启自动构建 resultMap, 字段规则又不符合 mybatis 的自动封装规则 */ - String propertyFormat = dbConfig.getPropertyFormat(); - String asProperty = this.property; - if (StringUtils.isNotBlank(propertyFormat)) { - asProperty = String.format(propertyFormat, this.property); - } - this.sqlSelect += (AS + asProperty); - } - - this.insertStrategy = this.chooseFieldStrategy(tableField.insertStrategy(), dbConfig.getInsertStrategy()); - this.updateStrategy = this.chooseFieldStrategy(tableField.updateStrategy(), dbConfig.getUpdateStrategy()); - this.whereStrategy = this.chooseFieldStrategy(tableField.whereStrategy(), dbConfig.getSelectStrategy()); - - if (StringUtils.isNotBlank(tableField.condition())) { - // 细粒度条件控制 - this.condition = tableField.condition(); - } - - // 字段是否注入查询 - this.select = tableField.select(); - } - - /** - * 优先使用单个字段注解,否则使用全局配置 - */ - private FieldStrategy chooseFieldStrategy(FieldStrategy fromAnnotation, FieldStrategy fromDbConfig) { - return fromAnnotation == FieldStrategy.DEFAULT ? fromDbConfig : fromAnnotation; - } - - /** - * 不存在 TableField 注解时, 使用的构造函数 - */ - public TableFieldInfo(GlobalConfig.DbConfig dbConfig, TableInfo tableInfo, Field field, Reflector reflector, - boolean existTableLogic,boolean isOrderBy) { - this(dbConfig,tableInfo,field,reflector,existTableLogic); - this.isOrderBy = isOrderBy; - if(isOrderBy){ - initOrderBy(field); - } - } - /** - * 不存在 TableField 注解时, 使用的构造函数 - */ - public TableFieldInfo(GlobalConfig.DbConfig dbConfig, TableInfo tableInfo, Field field, 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.el = this.property; - this.mapping = null; - this.insertStrategy = dbConfig.getInsertStrategy(); - this.updateStrategy = dbConfig.getUpdateStrategy(); - this.whereStrategy = dbConfig.getSelectStrategy(); - this.initLogicDelete(dbConfig, field, existTableLogic); - - String column = this.property; - if (tableInfo.isUnderCamel()) { - /* 开启字段下划线申明 */ - column = StringUtils.camelToUnderline(column); - } - if (dbConfig.isCapitalMode()) { - /* 开启字段全大写申明 */ - column = column.toUpperCase(); - } - - String columnFormat = dbConfig.getColumnFormat(); - if (StringUtils.isNotBlank(columnFormat)) { - column = String.format(columnFormat, column); - } - - this.column = column; - this.sqlSelect = column; - if (tableInfo.getResultMap() == null && !tableInfo.isAutoInitResultMap() && - TableInfoHelper.checkRelated(tableInfo.isUnderCamel(), this.property, this.column)) { - /* 未设置 resultMap 也未开启自动构建 resultMap, 字段规则又不符合 mybatis 的自动封装规则 */ - String propertyFormat = dbConfig.getPropertyFormat(); - String asProperty = this.property; - if (StringUtils.isNotBlank(propertyFormat)) { - asProperty = String.format(propertyFormat, this.property); - } - this.sqlSelect += (AS + asProperty); - } - } - - /** - * 排序初始化 - * @param field 字段 - */ - private void initOrderBy(Field field){ - OrderBy orderBy = field.getAnnotation(OrderBy.class); - if (null != orderBy) { - this.isOrderBy = true; - this.orderBySort = orderBy.sort(); - this.orderByType = orderBy.isDesc()?"desc":"asc"; - }else{ - this.isOrderBy = false; - } - } - - /** - * 逻辑删除初始化 - * - * @param dbConfig 数据库全局配置 - * @param field 字段属性对象 - */ - private void initLogicDelete(GlobalConfig.DbConfig dbConfig, Field field, boolean existTableLogic) { - /* 获取注解属性,逻辑处理字段 */ - TableLogic tableLogic = field.getAnnotation(TableLogic.class); - if (null != tableLogic) { - if (StringUtils.isNotBlank(tableLogic.value())) { - this.logicNotDeleteValue = tableLogic.value(); - } else { - this.logicNotDeleteValue = dbConfig.getLogicNotDeleteValue(); - } - if (StringUtils.isNotBlank(tableLogic.delval())) { - this.logicDeleteValue = tableLogic.delval(); - } else { - this.logicDeleteValue = dbConfig.getLogicDeleteValue(); - } - this.logicDelete = true; - } else if (!existTableLogic) { - String deleteField = dbConfig.getLogicDeleteField(); - if (StringUtils.isNotBlank(deleteField) && this.property.equals(deleteField)) { - this.logicNotDeleteValue = dbConfig.getLogicNotDeleteValue(); - this.logicDeleteValue = dbConfig.getLogicDeleteValue(); - this.logicDelete = true; - } - } - } - - /** - * 获取 ResultMapping - * - * @param configuration MybatisConfiguration - * @return ResultMapping - */ - public ResultMapping getResultMapping(final Configuration configuration) { - ResultMapping.Builder builder = new ResultMapping.Builder(configuration, property, - StringUtils.getTargetColumn(column), propertyType); - TypeHandlerRegistry registry = configuration.getTypeHandlerRegistry(); - if (jdbcType != null && jdbcType != JdbcType.UNDEFINED) { - builder.jdbcType(jdbcType); - } - if (typeHandler != null && typeHandler != UnknownTypeHandler.class) { - TypeHandler typeHandler = registry.getMappingTypeHandler(this.typeHandler); - if (typeHandler == null) { - typeHandler = registry.getInstance(propertyType, this.typeHandler); - // todo 这会有影响 registry.register(typeHandler); - } - builder.typeHandler(typeHandler); - } - return builder.build(); - } - -} diff --git a/src/main/java/com/github/yulichang/metadata/TableInfo.java b/src/main/java/com/github/yulichang/metadata/TableInfo.java deleted file mode 100644 index 271cc3e..0000000 --- a/src/main/java/com/github/yulichang/metadata/TableInfo.java +++ /dev/null @@ -1,234 +0,0 @@ -package com.github.yulichang.metadata; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.core.toolkit.Assert; -import com.baomidou.mybatisplus.core.toolkit.Constants; -import com.baomidou.mybatisplus.core.toolkit.StringUtils; -import lombok.AccessLevel; -import lombok.Data; -import lombok.Getter; -import lombok.Setter; -import lombok.experimental.Accessors; -import org.apache.ibatis.session.Configuration; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * 为自定义resultType提供resultMap - *

- * 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 fieldList; - /** - * 命名空间 (对应的 mapper 接口的全类名) - */ - private String currentNamespace; - /** - * MybatisConfiguration 标记 (Configuration内存地址值) - */ - @Getter - private Configuration configuration; - /** - * 是否开启下划线转驼峰 - *

- * 未注解指定字段名的情况下,用于自动从 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 orderByFields; - - public TableInfo(Class entityType) { - this.entityType = entityType; - } - - /** - * 获得注入的 SQL Statement - * - * @param sqlMethod MybatisPlus 支持 SQL 方法 - * @return SQL Statement - * @deprecated 3.4.0 如果存在的多mapper共用一个实体的情况,这里可能会出现获取命名空间错误的情况 - */ - @Deprecated - public String getSqlStatement(String sqlMethod) { - return currentNamespace + DOT + sqlMethod; - } - - /** - * 设置 Configuration - */ - void setConfiguration(Configuration configuration) { - Assert.notNull(configuration, "Error: You need Initialize MybatisConfiguration !"); - this.configuration = configuration; - this.underCamel = configuration.isMapUnderscoreToCamelCase(); - } - - /** - * 是否有主键 - * - * @return 是否有 - */ - public boolean havePK() { - return StringUtils.isNotBlank(keyColumn); - } - - void setFieldList(List fieldList) { - this.fieldList = fieldList; - AtomicInteger logicDeleted = new AtomicInteger(); - AtomicInteger version = new AtomicInteger(); - fieldList.forEach(i -> { - if (i.isLogicDelete()) { - this.withLogicDelete = true; - this.logicDeleteFieldInfo = i; - logicDeleted.getAndAdd(1); - } - if (i.isWithInsertFill()) { - this.withInsertFill = true; - } - if (i.isWithUpdateFill()) { - this.withUpdateFill = true; - } - if (i.isOrderBy()) { - if (null == this.orderByFields) { - this.orderByFields = new LinkedList<>(); - } - this.orderByFields.add(i); - } - if (i.isVersion()) { - this.withVersion = true; - this.versionFieldInfo = i; - version.getAndAdd(1); - } - }); - /* 校验字段合法性 */ - Assert.isTrue(logicDeleted.get() <= 1, "@TableLogic not support more than one in Class: \"%s\"", entityType.getName()); - Assert.isTrue(version.get() <= 1, "@Version not support more than one in Class: \"%s\"", entityType.getName()); - } - - public List getFieldList() { - return Collections.unmodifiableList(fieldList); - } - - @Deprecated - public boolean isLogicDelete() { - return withLogicDelete; - } -} diff --git a/src/main/java/com/github/yulichang/metadata/TableInfoHelper.java b/src/main/java/com/github/yulichang/metadata/TableInfoHelper.java deleted file mode 100644 index b3fbe24..0000000 --- a/src/main/java/com/github/yulichang/metadata/TableInfoHelper.java +++ /dev/null @@ -1,363 +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.*; -import org.apache.ibatis.logging.Log; -import org.apache.ibatis.logging.LogFactory; -import org.apache.ibatis.reflection.Reflector; -import org.apache.ibatis.reflection.ReflectorFactory; -import org.apache.ibatis.session.Configuration; - -import java.lang.reflect.Field; -import java.util.*; - -import static java.util.stream.Collectors.toList; - -/** - * 为自定义resultType提供resultMap - *

- * 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 excludePropertyList = excludeProperty != null && excludeProperty.length > 0 ? Arrays.asList(excludeProperty) : Collections.emptyList(); - /* 初始化字段相关 */ - initTableFields(clazz, globalConfig, tableInfo, excludePropertyList); - return tableInfo; - } - - /** - *

- * 初始化 表数据库类型,表名,resultMap - *

- * - * @param clazz 实体类 - * @param globalConfig 全局配置 - * @param tableInfo 数据库表反射信息 - * @return 需要排除的字段名 - */ - private static String[] initTableName(Class clazz, GlobalConfig globalConfig, TableInfo tableInfo) { - /* 数据库全局配置 */ - GlobalConfig.DbConfig dbConfig = globalConfig.getDbConfig(); - TableName table = clazz.getAnnotation(TableName.class); - - String tableName = clazz.getSimpleName(); - String tablePrefix = dbConfig.getTablePrefix(); - String schema = dbConfig.getSchema(); - boolean tablePrefixEffect = true; - String[] excludeProperty = null; - - if (table != null) { - if (StringUtils.isNotBlank(table.value())) { - tableName = table.value(); - if (StringUtils.isNotBlank(tablePrefix) && !table.keepGlobalPrefix()) { - tablePrefixEffect = false; - } - } else { - tableName = initTableNameWithDbConfig(tableName, dbConfig); - } - if (StringUtils.isNotBlank(table.schema())) { - schema = table.schema(); - } - /* 表结果集映射 */ - if (StringUtils.isNotBlank(table.resultMap())) { - tableInfo.setResultMap(table.resultMap()); - } - tableInfo.setAutoInitResultMap(table.autoResultMap()); - excludeProperty = table.excludeProperty(); - } else { - tableName = initTableNameWithDbConfig(tableName, dbConfig); - } - - String targetTableName = tableName; - if (StringUtils.isNotBlank(tablePrefix) && tablePrefixEffect) { - targetTableName = tablePrefix + targetTableName; - } - if (StringUtils.isNotBlank(schema)) { - targetTableName = schema + StringPool.DOT + targetTableName; - } - - tableInfo.setTableName(targetTableName); - - /* 开启了自定义 KEY 生成器 */ - if (CollectionUtils.isNotEmpty(dbConfig.getKeyGenerators())) { - tableInfo.setKeySequence(clazz.getAnnotation(KeySequence.class)); - } - return excludeProperty; - } - - /** - * 根据 DbConfig 初始化 表名 - * - * @param className 类名 - * @param dbConfig DbConfig - * @return 表名 - */ - private static String initTableNameWithDbConfig(String className, GlobalConfig.DbConfig dbConfig) { - String tableName = className; - // 开启表名下划线申明 - if (dbConfig.isTableUnderline()) { - tableName = StringUtils.camelToUnderline(tableName); - } - // 大写命名判断 - if (dbConfig.isCapitalMode()) { - tableName = tableName.toUpperCase(); - } else { - // 首字母小写 - tableName = StringUtils.firstToLowerCase(tableName); - } - return tableName; - } - - /** - *

- * 初始化 表主键,表字段 - *

- * - * @param clazz 实体类 - * @param globalConfig 全局配置 - * @param tableInfo 数据库表反射信息 - */ - private static void initTableFields(Class clazz, GlobalConfig globalConfig, TableInfo tableInfo, List excludeProperty) { - /* 数据库全局配置 */ - GlobalConfig.DbConfig dbConfig = globalConfig.getDbConfig(); - ReflectorFactory reflectorFactory = tableInfo.getConfiguration().getReflectorFactory(); - Reflector reflector = reflectorFactory.findForClass(clazz); - List list = getAllFields(clazz); - // 标记是否读取到主键 - boolean isReadPK = false; - // 是否存在 @TableId 注解 - boolean existTableId = isExistTableId(list); - // 是否存在 @TableLogic 注解 - boolean existTableLogic = isExistTableLogic(list); - // 是否存在 @OrderBy 注解 - boolean existOrderBy = isExistOrderBy(list); - - List fieldList = new ArrayList<>(list.size()); - for (Field field : list) { - if (excludeProperty.contains(field.getName())) { - continue; - } - - /* 主键ID 初始化 */ - if (existTableId) { - TableId tableId = field.getAnnotation(TableId.class); - if (tableId != null) { - if (isReadPK) { - throw ExceptionUtils.mpe("@TableId can't more than one in Class: \"%s\".", clazz.getName()); - } else { - initTableIdWithAnnotation(dbConfig, tableInfo, field, tableId, reflector); - isReadPK = true; - continue; - } - } - } else if (!isReadPK) { - isReadPK = initTableIdWithoutAnnotation(dbConfig, tableInfo, 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, existOrderBy)); - continue; - } - - /* 无 @TableField 注解的字段初始化 */ - fieldList.add(new TableFieldInfo(dbConfig, tableInfo, field, reflector, existTableLogic, existOrderBy)); - } - - /* 字段列表 */ - tableInfo.setFieldList(fieldList); - - /* 未发现主键注解,提示警告信息 */ - if (!isReadPK) { - logger.warn(String.format("Can not find table primary key in Class: \"%s\".", clazz.getName())); - } - } - - /** - *

- * 判断主键注解是否存在 - *

- * - * @param list 字段列表 - * @return true 为存在 @TableId 注解; - */ - public static boolean isExistTableId(List list) { - return list.stream().anyMatch(field -> field.isAnnotationPresent(TableId.class)); - } - - /** - *

- * 判断逻辑删除注解是否存在 - *

- * - * @param list 字段列表 - * @return true 为存在 @TableId 注解; - */ - public static boolean isExistTableLogic(List list) { - return list.stream().anyMatch(field -> field.isAnnotationPresent(TableLogic.class)); - } - - /** - *

- * 判断排序注解是否存在 - *

- * - * @param list 字段列表 - * @return true 为存在 @TableId 注解; - */ - public static boolean isExistOrderBy(List list) { - return list.stream().anyMatch(field -> field.isAnnotationPresent(OrderBy.class)); - } - - /** - *

- * 主键属性初始化 - *

- * - * @param dbConfig 全局配置信息 - * @param tableInfo 表信息 - * @param field 字段 - * @param tableId 注解 - * @param reflector Reflector - */ - private static void initTableIdWithAnnotation(GlobalConfig.DbConfig dbConfig, TableInfo tableInfo, - Field field, TableId tableId, Reflector reflector) { - boolean underCamel = tableInfo.isUnderCamel(); - final String property = field.getName(); - if (field.getAnnotation(TableField.class) != null) { - logger.warn(String.format("This \"%s\" is the table primary key by @TableId annotation in Class: \"%s\",So @TableField annotation will not work!", - property, tableInfo.getEntityType().getName())); - } - /* 主键策略( 注解 > 全局 ) */ - // 设置 Sequence 其他策略无效 - if (IdType.NONE == tableId.type()) { - tableInfo.setIdType(dbConfig.getIdType()); - } else { - tableInfo.setIdType(tableId.type()); - } - - /* 字段 */ - String column = property; - if (StringUtils.isNotBlank(tableId.value())) { - column = tableId.value(); - } else { - // 开启字段下划线申明 - if (underCamel) { - column = StringUtils.camelToUnderline(column); - } - // 全局大写命名 - if (dbConfig.isCapitalMode()) { - column = column.toUpperCase(); - } - } - final Class keyType = reflector.getGetterType(property); - if (keyType.isPrimitive()) { - logger.warn(String.format("This primary key of \"%s\" is primitive !不建议如此请使用包装类 in Class: \"%s\"", - property, tableInfo.getEntityType().getName())); - } - tableInfo.setKeyRelated(checkRelated(underCamel, property, column)) - .setKeyColumn(column) - .setKeyProperty(property) - .setKeyType(keyType); - } - - /** - *

- * 主键属性初始化 - *

- * - * @param tableInfo 表信息 - * @param field 字段 - * @param reflector Reflector - * @return true 继续下一个属性判断,返回 continue; - */ - private static boolean initTableIdWithoutAnnotation(GlobalConfig.DbConfig dbConfig, TableInfo tableInfo, - Field field, Reflector reflector) { - final String property = field.getName(); - if (DEFAULT_ID_NAME.equalsIgnoreCase(property)) { - if (field.getAnnotation(TableField.class) != null) { - logger.warn(String.format("This \"%s\" is the table primary key by default name for `id` in Class: \"%s\",So @TableField will not work!", - property, tableInfo.getEntityType().getName())); - } - String column = property; - if (dbConfig.isCapitalMode()) { - column = column.toUpperCase(); - } - final Class keyType = reflector.getGetterType(property); - if (keyType.isPrimitive()) { - logger.warn(String.format("This primary key of \"%s\" is primitive !不建议如此请使用包装类 in Class: \"%s\"", - property, tableInfo.getEntityType().getName())); - } - tableInfo.setKeyRelated(checkRelated(tableInfo.isUnderCamel(), property, column)) - .setIdType(dbConfig.getIdType()) - .setKeyColumn(column) - .setKeyProperty(property) - .setKeyType(keyType); - return true; - } - return false; - } - - /** - * 判定 related 的值 - *

- * 为 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); - } - } - - /** - *

- * 获取该类的所有属性列表 - *

- * - * @param clazz 反射类 - * @return 属性集合 - */ - public static List getAllFields(Class clazz) { - List fieldList = ReflectionKit.getFieldList(ClassUtils.getUserClass(clazz)); - return fieldList.stream() - .filter(field -> { - /* 过滤注解非表字段属性 */ - TableField tableField = field.getAnnotation(TableField.class); - return (tableField == null || tableField.exist()); - }).collect(toList()); - } -} diff --git a/src/main/java/com/github/yulichang/toolkit/LambdaUtils.java b/src/main/java/com/github/yulichang/toolkit/LambdaUtils.java index e8e098c..84332c2 100644 --- a/src/main/java/com/github/yulichang/toolkit/LambdaUtils.java +++ b/src/main/java/com/github/yulichang/toolkit/LambdaUtils.java @@ -1,18 +1,17 @@ package com.github.yulichang.toolkit; -import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException; + 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.ReflectionKit; -import com.baomidou.mybatisplus.core.toolkit.support.*; +import com.baomidou.mybatisplus.core.toolkit.support.ColumnCache; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import com.github.yulichang.toolkit.support.SerializedLambda; import org.apache.ibatis.reflection.property.PropertyNamer; -import java.lang.invoke.SerializedLambda; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; +import java.lang.ref.WeakReference; import java.util.Map; +import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import static java.util.Locale.ENGLISH; @@ -24,39 +23,46 @@ public final class LambdaUtils { /* ******* 自定义方法 *********** */ public static String getName(SFunction fn) { - return PropertyNamer.methodToProperty(extract(fn).getImplMethodName()); + return PropertyNamer.methodToProperty(resolve(fn).getImplMethodName()); } @SuppressWarnings("unchecked") public static Class getEntityClass(SFunction fn) { - return (Class) extract(fn).getInstantiatedClass(); + return (Class) resolve(fn).getInstantiatedType(); } /* ******* 自定义方法 结束 以下代码均为拷贝 *********** */ + /** * 字段映射 */ private static final Map> COLUMN_CACHE_MAP = new ConcurrentHashMap<>(); /** + * SerializedLambda 反序列化缓存 + */ + private static final Map> FUNC_CACHE = new ConcurrentHashMap<>(); + + /** + * 解析 lambda 表达式, 该方法只是调用了 {@link SerializedLambda#resolve(SFunction)} 中的方法,在此基础上加了缓存。 * 该缓存可能会在任意不定的时间被清除 * * @param func 需要解析的 lambda 对象 * @param 类型,被调用的 Function 对象的目标类型 * @return 返回解析后的结果 + * @see SerializedLambda#resolve(SFunction) */ - public static LambdaMeta extract(SFunction func) { - try { - Method method = func.getClass().getDeclaredMethod("writeReplace"); - return new SerializedLambdaMeta((SerializedLambda) ReflectionKit.setAccessible(method).invoke(func)); - } catch (NoSuchMethodException e) { - if (func instanceof Proxy) return new ProxyLambdaMeta((Proxy) func); - String message = "Cannot find method writeReplace, please make sure that the lambda composite class is currently passed in"; - throw new MybatisPlusException(message); - } catch (InvocationTargetException | IllegalAccessException e) { - throw new MybatisPlusException(e); - } + public static SerializedLambda resolve(SFunction func) { + Class clazz = func.getClass(); + String name = clazz.getName(); + return Optional.ofNullable(FUNC_CACHE.get(name)) + .map(WeakReference::get) + .orElseGet(() -> { + SerializedLambda lambda = SerializedLambda.resolve(func); + FUNC_CACHE.put(name, new WeakReference<>(lambda)); + return lambda; + }); } /** @@ -99,7 +105,7 @@ public final class LambdaUtils { } info.getFieldList().forEach(i -> - map.put(formatKey(i.getProperty()), new ColumnCache(i.getColumn(), i.getSqlSelect(), i.getMapping())) + map.put(formatKey(i.getProperty()), new ColumnCache(i.getColumn(), i.getSqlSelect())) ); return map; } diff --git a/src/main/java/com/github/yulichang/toolkit/sql/SqlScriptUtils.java b/src/main/java/com/github/yulichang/toolkit/sql/SqlScriptUtils.java new file mode 100644 index 0000000..8e54368 --- /dev/null +++ b/src/main/java/com/github/yulichang/toolkit/sql/SqlScriptUtils.java @@ -0,0 +1,221 @@ +package com.github.yulichang.toolkit.sql; + +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.TypeHandler; + +/** + *

+ * sql 脚本工具类 + *

+ * + * @author miemie + * @since 2018-08-15 + */ +@SuppressWarnings("serial") +public abstract class SqlScriptUtils implements Constants { + + /** + *

+ * 获取 带 if 标签的脚本 + *

+ * + * @param sqlScript sql 脚本片段 + * @return if 脚本 + */ + public static String convertIf(final String sqlScript, final String ifTest, boolean newLine) { + String newSqlScript = sqlScript; + if (newLine) { + newSqlScript = NEWLINE + newSqlScript + NEWLINE; + } + return String.format("%s", ifTest, newSqlScript); + } + + /** + *

+ * 获取 带 trim 标签的脚本 + *

+ * + * @param sqlScript sql 脚本片段 + * @param prefix 以...开头 + * @param suffix 以...结尾 + * @param prefixOverrides 干掉最前一个... + * @param suffixOverrides 干掉最后一个... + * @return trim 脚本 + */ + public static String convertTrim(final String sqlScript, final String prefix, final String suffix, + final String prefixOverrides, final String suffixOverrides) { + StringBuilder sb = new StringBuilder("").toString(); + } + + /** + *

+ * 生成 choose 标签的脚本 + *

+ * + * @param whenTest when 内 test 的内容 + * @param otherwise otherwise 内容 + * @return choose 脚本 + */ + public static String convertChoose(final String whenTest, final String whenSqlScript, final String otherwise) { + return "" + NEWLINE + + "" + NEWLINE + + "" + otherwise + "" + NEWLINE + + ""; + } + + /** + *

+ * 生成 foreach 标签的脚本 + *

+ * + * @param sqlScript foreach 内部的 sql 脚本 + * @param collection collection + * @param index index + * @param item item + * @param separator separator + * @return foreach 脚本 + */ + public static String convertForeach(final String sqlScript, final String collection, final String index, + final String item, final String separator) { + StringBuilder sb = new StringBuilder("").toString(); + } + + /** + *

+ * 生成 where 标签的脚本 + *

+ * + * @param sqlScript where 内部的 sql 脚本 + * @return where 脚本 + */ + public static String convertWhere(final String sqlScript) { + return "" + NEWLINE + sqlScript + NEWLINE + ""; + } + + /** + *

+ * 生成 set 标签的脚本 + *

+ * + * @param sqlScript set 内部的 sql 脚本 + * @return set 脚本 + */ + public static String convertSet(final String sqlScript) { + return "" + NEWLINE + sqlScript + NEWLINE + ""; + } + + /** + *

+ * 安全入参: #{入参} + *

+ * + * @param param 入参 + * @return 脚本 + */ + public static String safeParam(final String param) { + return safeParam(param, null); + } + + /** + *

+ * 安全入参: #{入参,mapping} + *

+ * + * @param param 入参 + * @param mapping 映射 + * @return 脚本 + */ + public static String safeParam(final String param, final String mapping) { + String target = HASH_LEFT_BRACE + param; + if (StringUtils.isBlank(mapping)) { + return target + RIGHT_BRACE; + } + return target + COMMA + mapping + RIGHT_BRACE; + } + + /** + *

+ * 非安全入参: ${入参} + *

+ * + * @param param 入参 + * @return 脚本 + */ + public static String unSafeParam(final String param) { + return DOLLAR_LEFT_BRACE + param + RIGHT_BRACE; + } + + public static String mappingTypeHandler(Class> typeHandler) { + if (typeHandler != null) { + return "typeHandler=" + typeHandler.getName(); + } + return null; + } + + public static String mappingJdbcType(JdbcType jdbcType) { + if (jdbcType != null) { + return "jdbcType=" + jdbcType.name(); + } + return null; + } + + public static String mappingNumericScale(Integer numericScale) { + if (numericScale != null) { + return "numericScale=" + numericScale; + } + return null; + } + + public static String convertParamMapping(Class> typeHandler, JdbcType jdbcType, Integer numericScale) { + if (typeHandler == null && jdbcType == null && numericScale == null) { + return null; + } + String mapping = null; + if (typeHandler != null) { + mapping = mappingTypeHandler(typeHandler); + } + if (jdbcType != null) { + mapping = appendMapping(mapping, mappingJdbcType(jdbcType)); + } + if (numericScale != null) { + mapping = appendMapping(mapping, mappingNumericScale(numericScale)); + } + return mapping; + } + + private static String appendMapping(String mapping, String other) { + if (mapping != null) { + return mapping + COMMA + other; + } + return other; + } +} diff --git a/src/main/java/com/github/yulichang/toolkit/support/SerializedLambda.java b/src/main/java/com/github/yulichang/toolkit/support/SerializedLambda.java new file mode 100644 index 0000000..366e73a --- /dev/null +++ b/src/main/java/com/github/yulichang/toolkit/support/SerializedLambda.java @@ -0,0 +1,128 @@ +package com.github.yulichang.toolkit.support; + +import com.baomidou.mybatisplus.core.toolkit.ClassUtils; +import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils; +import com.baomidou.mybatisplus.core.toolkit.SerializationUtils; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; + +import java.io.*; + +/** + * 这个类是从 {@link java.lang.invoke.SerializedLambda} 里面 copy 过来的, + * 字段信息完全一样 + *

负责将一个支持序列的 Function 序列化为 SerializedLambda

+ * + * @author HCL + * @since 2018/05/10 + */ +@SuppressWarnings("unused") +public class SerializedLambda implements Serializable { + + private static final long serialVersionUID = 8025925345765570181L; + + private Class capturingClass; + private String functionalInterfaceClass; + private String functionalInterfaceMethodName; + private String functionalInterfaceMethodSignature; + private String implClass; + private String implMethodName; + private String implMethodSignature; + private int implMethodKind; + private String instantiatedMethodType; + private Object[] capturedArgs; + + /** + * 通过反序列化转换 lambda 表达式,该方法只能序列化 lambda 表达式,不能序列化接口实现或者正常非 lambda 写法的对象 + * + * @param lambda lambda对象 + * @return 返回解析后的 SerializedLambda + */ + public static SerializedLambda resolve(SFunction lambda) { + if (!lambda.getClass().isSynthetic()) { + throw ExceptionUtils.mpe("该方法仅能传入 lambda 表达式产生的合成类"); + } + try (ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(SerializationUtils.serialize(lambda))) { + @Override + protected Class resolveClass(ObjectStreamClass objectStreamClass) throws IOException, ClassNotFoundException { + Class clazz; + try { + clazz = ClassUtils.toClassConfident(objectStreamClass.getName()); + } catch (Exception ex) { + clazz = super.resolveClass(objectStreamClass); + } + return clazz == java.lang.invoke.SerializedLambda.class ? SerializedLambda.class : clazz; + } + }) { + return (SerializedLambda) objIn.readObject(); + } catch (ClassNotFoundException | IOException e) { + throw ExceptionUtils.mpe("This is impossible to happen", e); + } + } + + /** + * 获取接口 class + * + * @return 返回 class 名称 + */ + public String getFunctionalInterfaceClassName() { + return normalizedName(functionalInterfaceClass); + } + + /** + * 获取实现的 class + * + * @return 实现类 + */ + public Class getImplClass() { + return ClassUtils.toClassConfident(getImplClassName()); + } + + /** + * 获取 class 的名称 + * + * @return 类名 + */ + public String getImplClassName() { + return normalizedName(implClass); + } + + /** + * 获取实现者的方法名称 + * + * @return 方法名称 + */ + public String getImplMethodName() { + return implMethodName; + } + + /** + * 正常化类名称,将类名称中的 / 替换为 . + * + * @param name 名称 + * @return 正常的类名 + */ + private String normalizedName(String name) { + return name.replace('/', '.'); + } + + /** + * @return 获取实例化方法的类型 + */ + public Class getInstantiatedType() { + String instantiatedTypeName = normalizedName(instantiatedMethodType.substring(2, instantiatedMethodType.indexOf(';'))); + return ClassUtils.toClassConfident(instantiatedTypeName); + } + + /** + * @return 字符串形式 + */ + @Override + public String toString() { + String interfaceName = getFunctionalInterfaceClassName(); + String implName = getImplClassName(); + return String.format("%s -> %s::%s", + interfaceName.substring(interfaceName.lastIndexOf('.') + 1), + implName.substring(implName.lastIndexOf('.') + 1), + implMethodName); + } +} diff --git a/src/main/java/com/github/yulichang/wrapper/MPJAbstractWrapper.java b/src/main/java/com/github/yulichang/wrapper/MPJAbstractWrapper.java index 3fc1fe6..c8bb8b5 100644 --- a/src/main/java/com/github/yulichang/wrapper/MPJAbstractWrapper.java +++ b/src/main/java/com/github/yulichang/wrapper/MPJAbstractWrapper.java @@ -8,10 +8,10 @@ import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments; import com.baomidou.mybatisplus.core.enums.SqlKeyword; import com.baomidou.mybatisplus.core.enums.SqlLike; import com.baomidou.mybatisplus.core.toolkit.*; -import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils; import com.baomidou.mybatisplus.core.toolkit.sql.SqlUtils; import com.baomidou.mybatisplus.core.toolkit.sql.StringEscape; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import com.github.yulichang.toolkit.sql.SqlScriptUtils; import com.github.yulichang.wrapper.interfaces.Compare; import com.github.yulichang.wrapper.interfaces.Func; import com.github.yulichang.wrapper.interfaces.Join;