Quellcode durchsuchen

fixed gitee issues/IL6C3

Chris vor 7 Jahren
Ursprung
Commit
5dfcad8ca2

+ 23 - 18
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/ReflectionKit.java

@@ -15,27 +15,17 @@
  */
 package com.baomidou.mybatisplus.core.toolkit;
 
-import static java.util.function.Function.identity;
-import static java.util.stream.Collectors.toCollection;
-import static java.util.stream.Collectors.toMap;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Stream;
-
+import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
 import org.apache.ibatis.logging.Log;
 import org.apache.ibatis.logging.LogFactory;
 
-import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.stream.Stream;
+
+import static java.util.function.Function.identity;
+import static java.util.stream.Collectors.toCollection;
+import static java.util.stream.Collectors.toMap;
 
 /**
  * <p>
@@ -63,6 +53,21 @@ public class ReflectionKit {
         return StringUtils.concatCapitalize(boolean.class.equals(fieldType) ? "is" : "get", str);
     }
 
+    /**
+     * <p>
+     * 反射 method 方法名,例如 setVersion
+     * </p>
+     *
+     * @param field Field
+     * @param str   属性的setter方法名称,e.g. setVersion
+     */
+    public static String setMethodCapitalize(Field field, final String str) {
+        Class<?> fieldType = field.getType();
+        // type of boolean's field, getter methodname is isGood(),
+        // setter methodname is setGood(boolean)
+        return StringUtils.concatCapitalize("set", str);
+    }
+
     /**
      * <p>
      * 获取 public get方法的值

+ 50 - 32
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/OptimisticLockerInterceptor.java

@@ -1,25 +1,5 @@
 package com.baomidou.mybatisplus.extension.plugins;
 
-import java.lang.reflect.Field;
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.apache.ibatis.binding.MapperMethod;
-import org.apache.ibatis.executor.Executor;
-import org.apache.ibatis.mapping.MappedStatement;
-import org.apache.ibatis.mapping.SqlCommandType;
-import org.apache.ibatis.plugin.Interceptor;
-import org.apache.ibatis.plugin.Intercepts;
-import org.apache.ibatis.plugin.Invocation;
-import org.apache.ibatis.plugin.Plugin;
-import org.apache.ibatis.plugin.Signature;
-
 import com.baomidou.mybatisplus.annotation.Version;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
@@ -27,6 +7,17 @@ import com.baomidou.mybatisplus.core.metadata.TableInfo;
 import com.baomidou.mybatisplus.core.toolkit.ClassUtils;
 import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
 import com.baomidou.mybatisplus.core.toolkit.TableInfoHelper;
+import org.apache.ibatis.binding.MapperMethod;
+import org.apache.ibatis.executor.Executor;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.mapping.SqlCommandType;
+import org.apache.ibatis.plugin.*;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.sql.Timestamp;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * <p>
@@ -72,9 +63,21 @@ public class OptimisticLockerInterceptor implements Interceptor {
             return invocation.proceed();
         }
         Object param = args[1];
+        // JavaBean class
+        Class<?> entityClass = null;
+        // optimistic, Version Field
+        Field versionField = null;
+        // optimistic field annotated by Version
+        String versionColumnName = null;
+        // new version value, Long, Integer ...
+        Object updatedVersionVal = null;
+
+        // wrapper = ew
+        Wrapper ew = null;
+        // entity = et
+        Object et = null;
         if (param instanceof MapperMethod.ParamMap) {
             MapperMethod.ParamMap map = (MapperMethod.ParamMap) param;
-            Wrapper ew = null;
             if (map.containsKey(NAME_ENTITY_WRAPPER)) {
                 // mapper.update(updEntity, QueryWrapper<>(whereEntity);
                 ew = (Wrapper) map.get(NAME_ENTITY_WRAPPER);
@@ -86,33 +89,33 @@ public class OptimisticLockerInterceptor implements Interceptor {
             //if(!map.containsKey(NAME_ENTITY)) {
             //    return invocation.proceed();
             //}
-            Object et = null;
             if (map.containsKey(NAME_ENTITY)) {
                 et = map.get(NAME_ENTITY);
             }
-            if (ew != null) {
+            if (ew != null) { // entityWrapper
                 Object entity = ew.getEntity();
                 if (entity != null) {
-                    Class<?> entityClass = ClassUtils.getUserClass(entity.getClass());
+                    entityClass = ClassUtils.getUserClass(entity.getClass());
                     EntityField ef = getVersionField(entityClass);
-                    Field versionField = ef == null ? null : ef.getField();
+                    versionField = ef == null ? null : ef.getField();
                     if (versionField != null) {
                         Object originalVersionVal = versionField.get(entity);
                         if (originalVersionVal != null) {
-                            versionField.set(et, getUpdatedVersionVal(originalVersionVal));
+                            updatedVersionVal = getUpdatedVersionVal(originalVersionVal);
+                            versionField.set(et, updatedVersionVal);
                         }
                     }
                 }
-            } else if (et != null) {
+            } else if (et != null) { // entity
                 String methodId = ms.getId();
                 String updateMethodName = methodId.substring(ms.getId().lastIndexOf(".") + 1);
                 if (PARAM_UPDATE_METHOD_NAME.equals(updateMethodName)) {
                     // update(entityClass, null) -->> update all. ignore version
                     return invocation.proceed();
                 }
-                Class<?> entityClass = ClassUtils.getUserClass(et.getClass());
+                entityClass = ClassUtils.getUserClass(et.getClass());
                 EntityField entityField = this.getVersionField(entityClass);
-                Field versionField = entityField == null ? null : entityField.getField();
+                versionField = entityField == null ? null : entityField.getField();
                 Object originalVersionVal;
                 if (versionField != null && (originalVersionVal = versionField.get(et)) != null) {
                     TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass);
@@ -134,7 +137,7 @@ public class OptimisticLockerInterceptor implements Interceptor {
                     }
                     String versionPropertyName = versionField.getName();
                     List<TableFieldInfo> fieldList = tableInfo.getFieldList();
-                    String versionColumnName = entityField.getColumnName();
+                    versionColumnName = entityField.getColumnName();
                     if (versionColumnName == null) {
                         for (TableFieldInfo tf : fieldList) {
                             if (versionPropertyName.equals(tf.getProperty())) {
@@ -144,7 +147,8 @@ public class OptimisticLockerInterceptor implements Interceptor {
                     }
                     if (versionColumnName != null) {
                         entityField.setColumnName(versionColumnName);
-                        entityMap.put(versionField.getName(), getUpdatedVersionVal(originalVersionVal));
+                        updatedVersionVal = getUpdatedVersionVal(originalVersionVal);
+                        entityMap.put(versionField.getName(), updatedVersionVal);
                         entityMap.put(MP_OPTLOCK_VERSION_ORIGINAL, originalVersionVal);
                         entityMap.put(MP_OPTLOCK_VERSION_COLUMN, versionColumnName);
                         entityMap.put(MP_OPTLOCK_ET_ORIGINAL, et);
@@ -153,7 +157,21 @@ public class OptimisticLockerInterceptor implements Interceptor {
                 }
             }
         }
-        return invocation.proceed();
+
+        Object resultObj = invocation.proceed();
+        if (Objects.equals(1, resultObj)) {
+            // setVersion, Long.class
+            String _setterMethodName = ReflectionKit.setMethodCapitalize(versionField, versionColumnName);
+            Class<?> _fieldType = versionField.getType();
+            if (ew != null) {
+                Method md = ew.getClass().getMethod(_setterMethodName, _fieldType);
+                Object o = md.invoke(ew, updatedVersionVal);
+            } else if (et != null) {
+                Method md = et.getClass().getMethod(_setterMethodName, _fieldType);
+                Object o = md.invoke(et, updatedVersionVal);
+            }
+        }
+        return resultObj;
     }
 
     /**

+ 7 - 8
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/base/entity/LogicTestData.java

@@ -1,17 +1,13 @@
 package com.baomidou.mybatisplus.test.base.entity;
 
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
 
-import com.baomidou.mybatisplus.annotation.FieldFill;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableLogic;
-import com.baomidou.mybatisplus.annotation.TableName;
-
-import lombok.Data;
-import lombok.experimental.Accessors;
-
 /**
  * @author meimie
  * @since 2018/6/7
@@ -36,4 +32,7 @@ public class LogicTestData {
     private LocalDateTime updateDatetime;
     @TableLogic
     private Boolean deleted;
+
+    @Version
+    private Long version;
 }

+ 31 - 19
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/mysql/MysqlTestDataMapperTest.java

@@ -1,5 +1,23 @@
 package com.baomidou.mybatisplus.test.mysql;
 
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.test.base.entity.LogicTestData;
+import com.baomidou.mybatisplus.test.base.entity.TestData;
+import com.baomidou.mybatisplus.test.base.mapper.LogicTestDataMapper;
+import com.baomidou.mybatisplus.test.base.mapper.TestDataMapper;
+import com.baomidou.mybatisplus.test.mysql.config.MysqlDb;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import javax.annotation.Resource;
 import java.io.IOException;
 import java.math.BigDecimal;
 import java.sql.SQLException;
@@ -11,25 +29,6 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import javax.annotation.Resource;
-
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.baomidou.mybatisplus.test.base.entity.LogicTestData;
-import com.baomidou.mybatisplus.test.base.entity.TestData;
-import com.baomidou.mybatisplus.test.base.mapper.LogicTestDataMapper;
-import com.baomidou.mybatisplus.test.base.mapper.TestDataMapper;
-import com.baomidou.mybatisplus.test.mysql.config.MysqlDb;
-
 /**
  * <p>
  * Mybatis Plus mysql Junit Test
@@ -101,6 +100,19 @@ public class MysqlTestDataMapperTest {
         logicMapper.deleteBatchIds(ids);
     }
 
+    @Test
+    public void optimisticUpdateById() {
+//        mapper.updateById(new TestData().setId(1014132604940615682L).setTestInt(1111111111));
+        LogicTestData et = new LogicTestData()
+            .setId(1019248035919613954L)
+            .setTestInt(999)
+            .setVersion(17L);
+        System.out.println("====1=====>>>" + JSON.toJSONString(et, true));
+        int r = logicMapper.updateById(et);
+        System.out.println("====2-1==r==>>>" + r);
+        System.out.println("====2-2=====>>>" + JSON.toJSONString(et, true));
+    }
+
     @Test
     public void updateById() {
         mapper.updateById(new TestData().setId(1014132604940615682L).setTestInt(1111111111));

+ 5 - 6
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/mysql/config/DBConfig.java

@@ -1,9 +1,5 @@
 package com.baomidou.mybatisplus.test.mysql.config;
 
-import java.sql.SQLException;
-
-import javax.sql.DataSource;
-
 import org.h2.Driver;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -11,6 +7,9 @@ import org.springframework.jdbc.datasource.DataSourceTransactionManager;
 import org.springframework.jdbc.datasource.SimpleDriverDataSource;
 import org.springframework.transaction.annotation.EnableTransactionManagement;
 
+import javax.sql.DataSource;
+import java.sql.SQLException;
+
 /**
  * @author miemie
  * @since 2018/6/7
@@ -23,10 +22,10 @@ public class DBConfig {
     public DataSource dataSource() throws SQLException {
         SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
         dataSource.setDriver(new Driver());
-        dataSource.setUrl("jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=UTF-8");
         dataSource.setDriverClass(com.mysql.jdbc.Driver.class);
+        dataSource.setUrl("jdbc:mysql://localhost:3306/mshop_saas?useSSL=false&useUnicode=true&characterEncoding=UTF-8");
         dataSource.setUsername("root");
-        dataSource.setPassword("123456");
+        dataSource.setPassword("MySQL5715");
         return dataSource;
     }
 

+ 22 - 8
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/mysql/config/MybatisPlusConfig.java

@@ -1,20 +1,21 @@
 package com.baomidou.mybatisplus.test.mysql.config;
 
-import javax.sql.DataSource;
-
-import org.apache.ibatis.session.SqlSessionFactory;
-import org.apache.ibatis.type.JdbcType;
-import org.mybatis.spring.annotation.MapperScan;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.core.MybatisConfiguration;
 import com.baomidou.mybatisplus.core.config.GlobalConfig;
 import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector;
+import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
 import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor;
 import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
 import com.baomidou.mybatisplus.test.mysql.MysqlMetaObjectHandler;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.apache.ibatis.type.JdbcType;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.sql.DataSource;
 
 /**
  * <p>
@@ -43,6 +44,9 @@ public class MybatisPlusConfig {
         PaginationInterceptor pagination = new PaginationInterceptor();
         configuration.addInterceptor(pagination);
 
+        /** 乐观锁插件 */
+        configuration.addInterceptor(new OptimisticLockerInterceptor());
+
         sqlSessionFactory.setConfiguration(configuration);
 //        pagination.setLocalPage(true);
 //        OptimisticLockerInterceptor optLock = new OptimisticLockerInterceptor();
@@ -56,6 +60,16 @@ public class MybatisPlusConfig {
         return sqlSessionFactory.getObject();
     }
 
+//    /**
+//     * 无效配置 --
+//     * 乐观锁插件
+//     * @return OptimisticLockerInterceptor
+//     */
+//    @Bean
+//    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
+//        return new OptimisticLockerInterceptor();
+//    }
+
     @Bean
     public GlobalConfig globalConfig() {
         GlobalConfig conf = new GlobalConfig();

+ 4 - 2
mybatis-plus/src/test/resources/mysql/test_data.ddl.sql

@@ -10,7 +10,8 @@ CREATE TABLE IF NOT EXISTS tb_test_data_logic (
     test_timestamp  timestamp,
     create_datetime datetime,
     update_datetime datetime,
-    deleted         tinyint(1) default 0
+    deleted         tinyint(1) default 0,
+    version        BIGINT default 0
 )
     ENGINE = innodb
     DEFAULT CHARSET = utf8;
@@ -26,7 +27,8 @@ CREATE TABLE IF NOT EXISTS tb_test_data (
     test_date_time  datetime,
     test_timestamp  timestamp,
     create_datetime datetime,
-    update_datetime datetime
+    update_datetime datetime,
+    version        BIGINT default 0
 )
     ENGINE = innodb
     DEFAULT CHARSET = utf8;