Browse Source

Merge pull request #3710 from nieqiurong/reflector

TableInfo新增原生Reflector反射操作.
qmdx 4 years ago
parent
commit
e33bf20c9a

+ 6 - 6
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/Wrapper.java

@@ -130,27 +130,27 @@ public abstract class Wrapper<T> implements ISqlSegment {
         if (tableInfo == null) {
         if (tableInfo == null) {
             return false;
             return false;
         }
         }
-        if (tableInfo.getFieldList().stream().anyMatch(e -> fieldStrategyMatch(entity, e))) {
+        if (tableInfo.getFieldList().stream().anyMatch(e -> fieldStrategyMatch(tableInfo, entity, e))) {
             return true;
             return true;
         }
         }
-        return StringUtils.isNotBlank(tableInfo.getKeyProperty()) ? Objects.nonNull(ReflectionKit.getFieldValue(entity, tableInfo.getKeyProperty())) : false;
+        return StringUtils.isNotBlank(tableInfo.getKeyProperty()) ? Objects.nonNull(tableInfo.getPropertyValue(entity, tableInfo.getKeyProperty())) : false;
     }
     }
 
 
     /**
     /**
      * 根据实体FieldStrategy属性来决定判断逻辑
      * 根据实体FieldStrategy属性来决定判断逻辑
      */
      */
-    private boolean fieldStrategyMatch(T entity, TableFieldInfo e) {
+    private boolean fieldStrategyMatch(TableInfo tableInfo, T entity, TableFieldInfo e) {
         switch (e.getWhereStrategy()) {
         switch (e.getWhereStrategy()) {
             case NOT_NULL:
             case NOT_NULL:
-                return Objects.nonNull(ReflectionKit.getFieldValue(entity, e.getProperty()));
+                return Objects.nonNull(tableInfo.getPropertyValue(entity, e.getProperty()));
             case IGNORED:
             case IGNORED:
                 return true;
                 return true;
             case NOT_EMPTY:
             case NOT_EMPTY:
-                return StringUtils.checkValNotNull(ReflectionKit.getFieldValue(entity, e.getProperty()));
+                return StringUtils.checkValNotNull(tableInfo.getPropertyValue(entity, e.getProperty()));
             case NEVER:
             case NEVER:
                 return false;
                 return false;
             default:
             default:
-                return Objects.nonNull(ReflectionKit.getFieldValue(entity, e.getProperty()));
+                return Objects.nonNull(tableInfo.getPropertyValue(entity, e.getProperty()));
         }
         }
     }
     }
 
 

+ 60 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/metadata/TableInfo.java

@@ -20,6 +20,7 @@ import com.baomidou.mybatisplus.annotation.KeySequence;
 import com.baomidou.mybatisplus.core.toolkit.Assert;
 import com.baomidou.mybatisplus.core.toolkit.Assert;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.Constants;
 import com.baomidou.mybatisplus.core.toolkit.Constants;
+import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
 import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
 import lombok.AccessLevel;
 import lombok.AccessLevel;
@@ -30,6 +31,7 @@ import lombok.experimental.Accessors;
 import org.apache.ibatis.mapping.ResultFlag;
 import org.apache.ibatis.mapping.ResultFlag;
 import org.apache.ibatis.mapping.ResultMap;
 import org.apache.ibatis.mapping.ResultMap;
 import org.apache.ibatis.mapping.ResultMapping;
 import org.apache.ibatis.mapping.ResultMapping;
+import org.apache.ibatis.reflection.Reflector;
 import org.apache.ibatis.session.Configuration;
 import org.apache.ibatis.session.Configuration;
 
 
 import java.util.*;
 import java.util.*;
@@ -178,10 +180,33 @@ public class TableInfo implements Constants {
     @Setter
     @Setter
     private List<TableFieldInfo> orderByFields = new LinkedList<>();
     private List<TableFieldInfo> orderByFields = new LinkedList<>();
 
 
+    /**
+     * @since 3.4.4
+     */
+    @Getter
+    private Reflector reflector;
+
+    /**
+     * @param entityType 实体类型
+     * @deprecated 3.4.4 {@link #TableInfo(Configuration, Class)}
+     */
+    @Deprecated
     public TableInfo(Class<?> entityType) {
     public TableInfo(Class<?> entityType) {
         this.entityType = entityType;
         this.entityType = entityType;
     }
     }
 
 
+    /**
+     * @param configuration 配置对象
+     * @param entityType    实体类型
+     * @since 3.4.4
+     */
+    public TableInfo(Configuration configuration, Class<?> entityType) {
+        this.configuration = configuration;
+        this.entityType = entityType;
+        this.reflector = configuration.getReflectorFactory().findForClass(entityType);
+        this.underCamel = configuration.isMapUnderscoreToCamelCase();
+    }
+
     /**
     /**
      * 获得注入的 SQL Statement
      * 获得注入的 SQL Statement
      *
      *
@@ -195,8 +220,10 @@ public class TableInfo implements Constants {
     }
     }
 
 
     /**
     /**
+     * @deprecated 3.4.4 {@link #TableInfo(Configuration, Class)}
      * 设置 Configuration
      * 设置 Configuration
      */
      */
+    @Deprecated
     void setConfiguration(Configuration configuration) {
     void setConfiguration(Configuration configuration) {
         Assert.notNull(configuration, "Error: You need Initialize MybatisConfiguration !");
         Assert.notNull(configuration, "Error: You need Initialize MybatisConfiguration !");
         this.configuration = configuration;
         this.configuration = configuration;
@@ -475,4 +502,37 @@ public class TableInfo implements Constants {
     public boolean isLogicDelete() {
     public boolean isLogicDelete() {
         return withLogicDelete;
         return withLogicDelete;
     }
     }
+
+    /**
+     * 获取对象属性值
+     *
+     * @param entity   对象
+     * @param property 属性名
+     * @return 属性值
+     * @since 3.4.4
+     */
+    public Object getPropertyValue(Object entity, String property) {
+        try {
+            return this.reflector.getGetInvoker(property).invoke(entity, null);
+        } catch (ReflectiveOperationException e) {
+            throw ExceptionUtils.mpe("Error: Cannot read property in %s.  Cause:", e, entity.getClass().getSimpleName());
+        }
+    }
+
+    /**
+     * 设置对象属性值
+     *
+     * @param entity   实体对象
+     * @param property 属性名
+     * @param values   参数
+     * @since 3.4.4
+     */
+    public void setPropertyValue(Object entity, String property, Object... values) {
+        try {
+            this.reflector.getSetInvoker(property).invoke(entity, values);
+        } catch (ReflectiveOperationException e) {
+            throw ExceptionUtils.mpe("Error: Cannot write property in %s.  Cause:", e, entity.getClass().getSimpleName());
+        }
+    }
+
 }
 }

+ 8 - 15
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/metadata/TableInfoHelper.java

@@ -29,7 +29,6 @@ import org.apache.ibatis.mapping.MappedStatement;
 import org.apache.ibatis.mapping.ResultMap;
 import org.apache.ibatis.mapping.ResultMap;
 import org.apache.ibatis.mapping.SqlCommandType;
 import org.apache.ibatis.mapping.SqlCommandType;
 import org.apache.ibatis.reflection.Reflector;
 import org.apache.ibatis.reflection.Reflector;
-import org.apache.ibatis.reflection.ReflectorFactory;
 import org.apache.ibatis.session.Configuration;
 import org.apache.ibatis.session.Configuration;
 
 
 import java.lang.reflect.Field;
 import java.lang.reflect.Field;
@@ -154,9 +153,8 @@ public class TableInfoHelper {
      */
      */
     private synchronized static TableInfo initTableInfo(Configuration configuration, String currentNamespace, Class<?> clazz) {
     private synchronized static TableInfo initTableInfo(Configuration configuration, String currentNamespace, Class<?> clazz) {
         /* 没有获取到缓存信息,则初始化 */
         /* 没有获取到缓存信息,则初始化 */
-        TableInfo tableInfo = new TableInfo(clazz);
+        TableInfo tableInfo = new TableInfo(configuration, clazz);
         tableInfo.setCurrentNamespace(currentNamespace);
         tableInfo.setCurrentNamespace(currentNamespace);
-        tableInfo.setConfiguration(configuration);
         GlobalConfig globalConfig = GlobalConfigUtils.getGlobalConfig(configuration);
         GlobalConfig globalConfig = GlobalConfigUtils.getGlobalConfig(configuration);
 
 
         /* 初始化表名相关 */
         /* 初始化表名相关 */
@@ -273,8 +271,7 @@ public class TableInfoHelper {
     private static void initTableFields(Class<?> clazz, GlobalConfig globalConfig, TableInfo tableInfo, List<String> excludeProperty) {
     private static void initTableFields(Class<?> clazz, GlobalConfig globalConfig, TableInfo tableInfo, List<String> excludeProperty) {
         /* 数据库全局配置 */
         /* 数据库全局配置 */
         GlobalConfig.DbConfig dbConfig = globalConfig.getDbConfig();
         GlobalConfig.DbConfig dbConfig = globalConfig.getDbConfig();
-        ReflectorFactory reflectorFactory = tableInfo.getConfiguration().getReflectorFactory();
-        Reflector reflector = reflectorFactory.findForClass(clazz);
+        Reflector reflector = tableInfo.getReflector();
         List<Field> list = getAllFields(clazz);
         List<Field> list = getAllFields(clazz);
         // 标记是否读取到主键
         // 标记是否读取到主键
         boolean isReadPK = false;
         boolean isReadPK = false;
@@ -300,11 +297,11 @@ public class TableInfoHelper {
                         throw ExceptionUtils.mpe("@TableId can't more than one in Class: \"%s\".", clazz.getName());
                         throw ExceptionUtils.mpe("@TableId can't more than one in Class: \"%s\".", clazz.getName());
                     }
                     }
 
 
-                    initTableIdWithAnnotation(dbConfig, tableInfo, field, tableId, reflector);
+                    initTableIdWithAnnotation(dbConfig, tableInfo, field, tableId);
                     isPK = isReadPK = true;
                     isPK = isReadPK = true;
                 }
                 }
             } else if (!isReadPK) {
             } else if (!isReadPK) {
-                isPK = isReadPK = initTableIdWithoutAnnotation(dbConfig, tableInfo, field, reflector);
+                isPK = isReadPK = initTableIdWithoutAnnotation(dbConfig, tableInfo, field);
 
 
             }
             }
 
 
@@ -381,10 +378,8 @@ public class TableInfoHelper {
      * @param tableInfo 表信息
      * @param tableInfo 表信息
      * @param field     字段
      * @param field     字段
      * @param tableId   注解
      * @param tableId   注解
-     * @param reflector Reflector
      */
      */
-    private static void initTableIdWithAnnotation(GlobalConfig.DbConfig dbConfig, TableInfo tableInfo,
-                                                  Field field, TableId tableId, Reflector reflector) {
+    private static void initTableIdWithAnnotation(GlobalConfig.DbConfig dbConfig, TableInfo tableInfo, Field field, TableId tableId) {
         boolean underCamel = tableInfo.isUnderCamel();
         boolean underCamel = tableInfo.isUnderCamel();
         final String property = field.getName();
         final String property = field.getName();
         if (field.getAnnotation(TableField.class) != null) {
         if (field.getAnnotation(TableField.class) != null) {
@@ -413,7 +408,7 @@ public class TableInfoHelper {
                 column = column.toUpperCase();
                 column = column.toUpperCase();
             }
             }
         }
         }
-        final Class<?> keyType = reflector.getGetterType(property);
+        final Class<?> keyType = tableInfo.getReflector().getGetterType(property);
         if (keyType.isPrimitive()) {
         if (keyType.isPrimitive()) {
             logger.warn(String.format("This primary key of \"%s\" is primitive !不建议如此请使用包装类 in Class: \"%s\"",
             logger.warn(String.format("This primary key of \"%s\" is primitive !不建议如此请使用包装类 in Class: \"%s\"",
                 property, tableInfo.getEntityType().getName()));
                 property, tableInfo.getEntityType().getName()));
@@ -431,11 +426,9 @@ public class TableInfoHelper {
      *
      *
      * @param tableInfo 表信息
      * @param tableInfo 表信息
      * @param field     字段
      * @param field     字段
-     * @param reflector Reflector
      * @return true 继续下一个属性判断,返回 continue;
      * @return true 继续下一个属性判断,返回 continue;
      */
      */
-    private static boolean initTableIdWithoutAnnotation(GlobalConfig.DbConfig dbConfig, TableInfo tableInfo,
-                                                        Field field, Reflector reflector) {
+    private static boolean initTableIdWithoutAnnotation(GlobalConfig.DbConfig dbConfig, TableInfo tableInfo, Field field) {
         final String property = field.getName();
         final String property = field.getName();
         if (DEFAULT_ID_NAME.equalsIgnoreCase(property)) {
         if (DEFAULT_ID_NAME.equalsIgnoreCase(property)) {
             if (field.getAnnotation(TableField.class) != null) {
             if (field.getAnnotation(TableField.class) != null) {
@@ -446,7 +439,7 @@ public class TableInfoHelper {
             if (dbConfig.isCapitalMode()) {
             if (dbConfig.isCapitalMode()) {
                 column = column.toUpperCase();
                 column = column.toUpperCase();
             }
             }
-            final Class<?> keyType = reflector.getGetterType(property);
+            final Class<?> keyType = tableInfo.getReflector().getGetterType(property);
             if (keyType.isPrimitive()) {
             if (keyType.isPrimitive()) {
                 logger.warn(String.format("This primary key of \"%s\" is primitive !不建议如此请使用包装类 in Class: \"%s\"",
                 logger.warn(String.format("This primary key of \"%s\" is primitive !不建议如此请使用包装类 in Class: \"%s\"",
                     property, tableInfo.getEntityType().getName()));
                     property, tableInfo.getEntityType().getName()));

+ 3 - 1
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/activerecord/Model.java

@@ -18,6 +18,7 @@ package com.baomidou.mybatisplus.extension.activerecord;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.enums.SqlMethod;
 import com.baomidou.mybatisplus.core.enums.SqlMethod;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.metadata.TableInfo;
 import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
 import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
 import com.baomidou.mybatisplus.core.toolkit.*;
 import com.baomidou.mybatisplus.core.toolkit.*;
 import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
 import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
@@ -270,7 +271,8 @@ public abstract class Model<T extends Model<?>> implements Serializable {
      * 主键值
      * 主键值
      */
      */
     public Serializable pkVal() {
     public Serializable pkVal() {
-        return (Serializable) ReflectionKit.getFieldValue(this, TableInfoHelper.getTableInfo(this.entityClass).getKeyProperty());
+        TableInfo tableInfo = TableInfoHelper.getTableInfo(this.entityClass);
+        return (Serializable) tableInfo.getPropertyValue(this, tableInfo.getKeyProperty());
     }
     }
 
 
     /**
     /**

+ 2 - 2
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/service/impl/ServiceImpl.java

@@ -161,7 +161,7 @@ public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
             Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!");
             Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!");
             String keyProperty = tableInfo.getKeyProperty();
             String keyProperty = tableInfo.getKeyProperty();
             Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!");
             Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!");
-            Object idVal = ReflectionKit.getFieldValue(entity, tableInfo.getKeyProperty());
+            Object idVal = tableInfo.getPropertyValue(entity, tableInfo.getKeyProperty());
             return StringUtils.checkValNull(idVal) || Objects.isNull(getById((Serializable) idVal)) ? save(entity) : updateById(entity);
             return StringUtils.checkValNull(idVal) || Objects.isNull(getById((Serializable) idVal)) ? save(entity) : updateById(entity);
         }
         }
         return false;
         return false;
@@ -175,7 +175,7 @@ public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
         String keyProperty = tableInfo.getKeyProperty();
         String keyProperty = tableInfo.getKeyProperty();
         Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!");
         Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!");
         return SqlHelper.saveOrUpdateBatch(this.entityClass, this.mapperClass, this.log, entityList, batchSize, (sqlSession, entity) -> {
         return SqlHelper.saveOrUpdateBatch(this.entityClass, this.mapperClass, this.log, entityList, batchSize, (sqlSession, entity) -> {
-            Object idVal = ReflectionKit.getFieldValue(entity, keyProperty);
+            Object idVal = tableInfo.getPropertyValue(entity, keyProperty);
             return StringUtils.checkValNull(idVal)
             return StringUtils.checkValNull(idVal)
                 || CollectionUtils.isEmpty(sqlSession.selectList(getSqlStatement(SqlMethod.SELECT_BY_ID), entity));
                 || CollectionUtils.isEmpty(sqlSession.selectList(getSqlStatement(SqlMethod.SELECT_BY_ID), entity));
         }, (sqlSession, entity) -> {
         }, (sqlSession, entity) -> {