Pārlūkot izejas kodu

!299 fix: #I88SRT - DataChangeRecorderInnerInterceptor lambda方法记录数据错误
Merge pull request !299 from yuxiaobin/3.0

yuxiaobin 1 gadu atpakaļ
vecāks
revīzija
0f09913836

+ 183 - 31
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DataChangeRecorderInnerInterceptor.java

@@ -15,38 +15,70 @@
  */
 package com.baomidou.mybatisplus.extension.plugins.inner;
 
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.ibatis.executor.statement.StatementHandler;
+import org.apache.ibatis.mapping.BoundSql;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.mapping.ParameterMapping;
+import org.apache.ibatis.mapping.SqlCommandType;
+import org.apache.ibatis.reflection.MetaObject;
+import org.apache.ibatis.reflection.SystemMetaObject;
+import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.baomidou.mybatisplus.annotation.IEnum;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
+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.PluginUtils;
 import com.baomidou.mybatisplus.extension.parser.JsqlParserGlobal;
+
 import lombok.Data;
 import net.sf.jsqlparser.expression.Expression;
 import net.sf.jsqlparser.expression.JdbcParameter;
+import net.sf.jsqlparser.expression.RowConstructor;
+import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
 import net.sf.jsqlparser.schema.Column;
 import net.sf.jsqlparser.schema.Table;
 import net.sf.jsqlparser.statement.Statement;
 import net.sf.jsqlparser.statement.delete.Delete;
 import net.sf.jsqlparser.statement.insert.Insert;
-import net.sf.jsqlparser.statement.select.*;
+import net.sf.jsqlparser.statement.select.AllColumns;
+import net.sf.jsqlparser.statement.select.FromItem;
+import net.sf.jsqlparser.statement.select.PlainSelect;
+import net.sf.jsqlparser.statement.select.Select;
+import net.sf.jsqlparser.statement.select.SelectBody;
+import net.sf.jsqlparser.statement.select.SelectExpressionItem;
+import net.sf.jsqlparser.statement.select.SelectItem;
+import net.sf.jsqlparser.statement.select.SetOperationList;
 import net.sf.jsqlparser.statement.update.Update;
 import net.sf.jsqlparser.statement.update.UpdateSet;
-import org.apache.ibatis.executor.statement.StatementHandler;
-import org.apache.ibatis.mapping.BoundSql;
-import org.apache.ibatis.mapping.MappedStatement;
-import org.apache.ibatis.mapping.ParameterMapping;
-import org.apache.ibatis.mapping.SqlCommandType;
-import org.apache.ibatis.reflection.MetaObject;
-import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.Reader;
-import java.math.BigDecimal;
-import java.sql.*;
-import java.util.Date;
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
+import net.sf.jsqlparser.statement.values.ValuesStatement;
 
 /**
  * <p>
@@ -92,6 +124,7 @@ import java.util.concurrent.ConcurrentHashMap;
  * @date 2022-8-21
  */
 public class DataChangeRecorderInnerInterceptor implements InnerInterceptor {
+
     protected final Logger logger = LoggerFactory.getLogger(this.getClass());
     @SuppressWarnings("unused")
     public static final String IGNORED_TABLE_COLUMN_PROPERTIES = "ignoredTableColumns";
@@ -241,10 +274,12 @@ public class DataChangeRecorderInnerInterceptor implements InnerInterceptor {
      * @return
      */
     private List<DataChangedRecord> compareAndGetUpdatedColumnDatas(String tableName, BoundSql updateSql, Statement statement, OriginalDataObj originalDataObj) {
-        Map<String, Object> columnNameValMap = new HashMap<>(updateSql.getParameterMappings().size());
+        Map<String, String> columnNameValMap = new HashMap<>(updateSql.getParameterMappings().size());
+        Map<Integer, String> columnSetIndexMap = new HashMap<>(updateSql.getParameterMappings().size());
         List<Column> selectItemsFromUpdateSql = new ArrayList<>();
         if (statement instanceof Update) {
             Update updateStmt = (Update) statement;
+            int index = 0;
             for (UpdateSet updateSet : updateStmt.getUpdateSets()) {
                 selectItemsFromUpdateSql.addAll(updateSet.getColumns());
                 final List<Expression> updateList = updateSet.getExpressions();
@@ -253,41 +288,63 @@ public class DataChangeRecorderInnerInterceptor implements InnerInterceptor {
                     if (!(updateExps instanceof JdbcParameter)) {
                         columnNameValMap.put(updateSet.getColumns().get(i).getColumnName().toUpperCase(), updateExps.toString());
                     }
+                    columnSetIndexMap.put(index++, updateSet.getColumns().get(i).getColumnName().toUpperCase());
                 }
             }
         } else if (statement instanceof Insert) {
-            selectItemsFromUpdateSql.addAll(((Insert) statement).getColumns());
+            Insert insert = (Insert) statement;
+            selectItemsFromUpdateSql.addAll(insert.getColumns());
+            columnNameValMap.putAll(detectInsertColumnValuesNonJdbcParameters(insert));
         }
         Map<String, String> relatedColumnsUpperCaseWithoutUnderline = new HashMap<>(selectItemsFromUpdateSql.size(), 1);
         for (Column item : selectItemsFromUpdateSql) {
             //FIRSTNAME: FIRST_NAME/FIRST-NAME/FIRST$NAME/FIRST.NAME
-            relatedColumnsUpperCaseWithoutUnderline.put(item.toString().replaceAll("[._\\-$]", "").toUpperCase(), item.toString().toUpperCase());
+            relatedColumnsUpperCaseWithoutUnderline.put(item.getColumnName().replaceAll("[._\\-$]", "").toUpperCase(), item.getColumnName().toUpperCase());
         }
-        MetaObject metaObject = PluginUtils.getMetaObject(updateSql.getParameterObject());
-
+        MetaObject metaObject = SystemMetaObject.forObject(updateSql.getParameterObject());
+        int index = 0;
         for (ParameterMapping parameterMapping : updateSql.getParameterMappings()) {
             String propertyName = parameterMapping.getProperty();
             if (propertyName.startsWith("ew.paramNameValuePairs")) {
+                ++index;
                 continue;
             }
             String[] arr = propertyName.split("\\.");
             String propertyNameTrim = arr[arr.length - 1].replace("_", "").toUpperCase();
-            if (relatedColumnsUpperCaseWithoutUnderline.containsKey(propertyNameTrim)) {
-                columnNameValMap.put(relatedColumnsUpperCaseWithoutUnderline.get(propertyNameTrim), metaObject.getValue(propertyName));
+            try {
+                final String columnName = columnSetIndexMap.getOrDefault(index++, getColumnNameByProperty(propertyNameTrim, tableName));
+                if (relatedColumnsUpperCaseWithoutUnderline.containsKey(propertyNameTrim)) {
+                    final String colkey = relatedColumnsUpperCaseWithoutUnderline.get(propertyNameTrim);
+                    final String val = String.valueOf(metaObject.getValue(propertyName));
+                    if (columnNameValMap.containsKey(colkey)) {
+                        columnNameValMap.put(relatedColumnsUpperCaseWithoutUnderline.get(propertyNameTrim), String.valueOf(columnNameValMap.get(colkey)).replace("?", val));
+                    }
+                    if (columnName != null && !columnNameValMap.containsKey(columnName)) {
+                        columnNameValMap.put(columnName, val);
+                    }
+                } else {
+                    if (columnName != null) {
+                        columnNameValMap.put(columnName, String.valueOf(metaObject.getValue(propertyName)));
+                    }
+                }
+            } catch (Exception e) {
+                logger.warn("get value error,propertyName:{},parameterMapping:{}", propertyName, parameterMapping);
             }
         }
+        dealWithUpdateWrapper(columnSetIndexMap, columnNameValMap, updateSql);
 
         final Set<String> ignoredColumns = ignoredTableColumns.get(tableName.toUpperCase());
         if (originalDataObj == null || originalDataObj.isEmpty()) {
             DataChangedRecord oneRecord = new DataChangedRecord();
             List<DataColumnChangeResult> updateColumns = new ArrayList<>(columnNameValMap.size());
-            for (Map.Entry<String, Object> ety : columnNameValMap.entrySet()) {
+            for (Map.Entry<String, String> ety : columnNameValMap.entrySet()) {
                 String columnName = ety.getKey();
                 if ((ignoredColumns == null || !ignoredColumns.contains(columnName)) && !ignoreAllColumns.contains(columnName)) {
                     updateColumns.add(DataColumnChangeResult.constrcutByUpdateVal(columnName, ety.getValue()));
                 }
             }
             oneRecord.setUpdatedColumns(updateColumns);
+//            oneRecord.setUpdatedColumns(Collections.EMPTY_LIST);
             return Collections.singletonList(oneRecord);
         }
         List<DataChangedRecord> originalDataList = originalDataObj.getOriginalDataObj();
@@ -300,6 +357,99 @@ public class DataChangeRecorderInnerInterceptor implements InnerInterceptor {
         return updateDataList;
     }
 
+    @SuppressWarnings("rawtypes")
+    private void dealWithUpdateWrapper(Map<Integer, String> columnSetIndexMap, Map<String, String> columnNameValMap, BoundSql updateSql){
+        if (columnSetIndexMap.size() <= columnNameValMap.size()) {
+            return;
+        }
+        MetaObject mpgenVal = SystemMetaObject.forObject(updateSql.getParameterObject());
+        Object ew = mpgenVal.getValue("ew");
+        if (ew instanceof UpdateWrapper || ew instanceof LambdaUpdateWrapper) {
+            final String sqlSet = ew instanceof UpdateWrapper ? ((UpdateWrapper) ew).getSqlSet() : ((LambdaUpdateWrapper) ew).getSqlSet();// columnName=#{val}
+            if (sqlSet == null) {
+                return;
+            }
+            MetaObject ewMeta = SystemMetaObject.forObject(ew);
+            final Map paramNameValuePairs = (Map) ewMeta.getValue("paramNameValuePairs");
+            String[] setItems = sqlSet.split(",");
+            for (String setItem : setItems) {
+                //age=#{ew.paramNameValuePairs.MPGENVAL1}
+                String[] nameAndValuePair = setItem.split("=", 2);
+                if (nameAndValuePair.length == 2) {
+                    String setColName = nameAndValuePair[0].trim().toUpperCase();
+                    String setColVal = nameAndValuePair[1].trim();//#{.mp}
+                    if (columnSetIndexMap.containsValue(setColName)) {
+                        String[] mpGenKeyArray = setColVal.split("\\.");
+                        String mpGenKey = mpGenKeyArray[mpGenKeyArray.length - 1].replace("}", "");
+                        final Object setVal = paramNameValuePairs.get(mpGenKey);
+                        if (setVal instanceof IEnum) {
+                            columnNameValMap.put(setColName, String.valueOf(((IEnum<?>) setVal).getValue()));
+                        } else {
+                            columnNameValMap.put(setColName, String.valueOf(setVal));
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private Map<String, String> detectInsertColumnValuesNonJdbcParameters(Insert insert) {
+        Map<String, String> columnNameValMap = new HashMap<>(4);
+        final Select select = insert.getSelect();
+        List<Column> columns = insert.getColumns();
+        if (select != null && select.getSelectBody() instanceof SetOperationList) {
+            SetOperationList setOperationList = (SetOperationList) select.getSelectBody();
+            final List<SelectBody> selects = setOperationList.getSelects();
+            if (CollectionUtils.isEmpty(selects)) {
+                return columnNameValMap;
+            }
+            final SelectBody selectBody = selects.get(0);
+            if (!(selectBody instanceof ValuesStatement)) {
+                return columnNameValMap;
+            }
+            ValuesStatement valuesStatement = (ValuesStatement) selectBody;
+            if (valuesStatement.getExpressions() instanceof ExpressionList) {
+                ExpressionList expressionList = (ExpressionList) valuesStatement.getExpressions();
+                List<Expression> expressions = expressionList.getExpressions();
+                for (Expression expression : expressions) {
+                    if (expression instanceof RowConstructor) {
+                        final ExpressionList exprList = ((RowConstructor) expression).getExprList();
+                        if (exprList != null) {
+                            final List<Expression> insertExpList = exprList.getExpressions();
+                            for (int i = 0; i < insertExpList.size(); ++i) {
+                                Expression e = insertExpList.get(i);
+                                if (!(e instanceof JdbcParameter)) {
+                                    final String columnName = columns.get(i).getColumnName();
+                                    final String val = e.toString();
+                                    columnNameValMap.put(columnName, val);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return columnNameValMap;
+    }
+
+    private String getColumnNameByProperty(String propertyName, String tableName) {
+        for (TableInfo tableInfo : TableInfoHelper.getTableInfos()) {
+            if (tableName.equalsIgnoreCase(tableInfo.getTableName())) {
+                final List<TableFieldInfo> fieldList = tableInfo.getFieldList();
+                if (CollectionUtils.isEmpty(fieldList)) {
+                    return propertyName;
+                }
+                for (TableFieldInfo tableFieldInfo : fieldList) {
+                    if (propertyName.equalsIgnoreCase(tableFieldInfo.getProperty())) {
+                        return tableFieldInfo.getColumn().toUpperCase();
+                    }
+                }
+                return propertyName;
+            }
+        }
+        return propertyName;
+    }
+
 
     private Map<String, Object> buildParameterObjectMap(BoundSql boundSql) {
         MetaObject metaObject = PluginUtils.getMetaObject(boundSql.getParameterObject());
@@ -587,6 +737,7 @@ public class DataChangeRecorderInnerInterceptor implements InnerInterceptor {
 
     @Data
     public static class OperationResult {
+
         private String operation;
         private boolean recordStatus;
         private String tableName;
@@ -614,11 +765,11 @@ public class DataChangeRecorderInnerInterceptor implements InnerInterceptor {
         @Override
         public String toString() {
             return "{" +
-                    "\"tableName\":\"" + tableName + "\"," +
-                    "\"operation\":\"" + operation + "\"," +
-                    "\"recordStatus\":\"" + recordStatus + "\"," +
-                    "\"changedData\":" + changedData + "," +
-                    "\"cost(ms)\":" + cost + "}";
+                "\"tableName\":\"" + tableName + "\"," +
+                "\"operation\":\"" + operation + "\"," +
+                "\"recordStatus\":\"" + recordStatus + "\"," +
+                "\"changedData\":" + changedData + "," +
+                "\"cost(ms)\":" + cost + "}";
         }
     }
 
@@ -738,12 +889,13 @@ public class DataChangeRecorderInnerInterceptor implements InnerInterceptor {
 
     @Data
     public static class DataChangedRecord {
+
         private String pkColumnName;
         private Object pkColumnVal;
         private List<DataColumnChangeResult> originalColumnDatas;
         private List<DataColumnChangeResult> updatedColumns;
 
-        public boolean hasUpdate(Map<String, Object> columnNameValMap, Set<String> ignoredColumns, Set<String> ignoreAllColumns) {
+        public boolean hasUpdate(Map<String, String> columnNameValMap, Set<String> ignoredColumns, Set<String> ignoreAllColumns) {
             if (originalColumnDatas == null) {
                 return true;
             }

+ 37 - 13
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DataPermissionInterceptor.java

@@ -15,28 +15,38 @@
  */
 package com.baomidou.mybatisplus.extension.plugins.inner;
 
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.ibatis.executor.Executor;
+import org.apache.ibatis.executor.statement.StatementHandler;
+import org.apache.ibatis.mapping.BoundSql;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.mapping.SqlCommandType;
+import org.apache.ibatis.session.ResultHandler;
+import org.apache.ibatis.session.RowBounds;
+
 import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
 import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler;
 import com.baomidou.mybatisplus.extension.plugins.handler.MultiDataPermissionHandler;
-import lombok.*;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
 import net.sf.jsqlparser.expression.Expression;
 import net.sf.jsqlparser.schema.Table;
 import net.sf.jsqlparser.statement.delete.Delete;
-import net.sf.jsqlparser.statement.select.*;
+import net.sf.jsqlparser.statement.select.PlainSelect;
+import net.sf.jsqlparser.statement.select.Select;
+import net.sf.jsqlparser.statement.select.SelectBody;
+import net.sf.jsqlparser.statement.select.SetOperationList;
+import net.sf.jsqlparser.statement.select.WithItem;
 import net.sf.jsqlparser.statement.update.Update;
-import org.apache.ibatis.executor.Executor;
-import org.apache.ibatis.executor.statement.StatementHandler;
-import org.apache.ibatis.mapping.BoundSql;
-import org.apache.ibatis.mapping.MappedStatement;
-import org.apache.ibatis.mapping.SqlCommandType;
-import org.apache.ibatis.session.ResultHandler;
-import org.apache.ibatis.session.RowBounds;
-
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.util.List;
 
 /**
  * 数据权限处理器
@@ -51,8 +61,10 @@ import java.util.List;
 @EqualsAndHashCode(callSuper = true)
 @SuppressWarnings({"rawtypes"})
 public class DataPermissionInterceptor extends BaseMultiTableInnerInterceptor implements InnerInterceptor {
+
     private DataPermissionHandler dataPermissionHandler;
 
+    @SuppressWarnings("RedundantThrows")
     @Override
     public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
         if (InterceptorIgnoreHelper.willIgnoreDataPermission(ms.getId())) {
@@ -78,6 +90,9 @@ public class DataPermissionInterceptor extends BaseMultiTableInnerInterceptor im
 
     @Override
     protected void processSelect(Select select, int index, String sql, Object obj) {
+        if (dataPermissionHandler == null) {
+            return;
+        }
         if (dataPermissionHandler instanceof MultiDataPermissionHandler) {
             // 参照 com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor.processSelect 做的修改
             final String whereSegment = (String) obj;
@@ -106,6 +121,9 @@ public class DataPermissionInterceptor extends BaseMultiTableInnerInterceptor im
      * @param whereSegment 查询条件片段
      */
     protected void setWhere(PlainSelect plainSelect, String whereSegment) {
+        if (dataPermissionHandler == null) {
+            return;
+        }
         // 兼容旧版的数据权限处理
         final Expression sqlSegment = dataPermissionHandler.getSqlSegment(plainSelect.getWhere(), whereSegment);
         if (null != sqlSegment) {
@@ -136,6 +154,9 @@ public class DataPermissionInterceptor extends BaseMultiTableInnerInterceptor im
     }
 
     protected Expression getUpdateOrDeleteExpression(final Table table, final Expression where, final String whereSegment) {
+        if (dataPermissionHandler == null) {
+            return null;
+        }
         if (dataPermissionHandler instanceof MultiDataPermissionHandler) {
             return andExpression(table, where, whereSegment);
         } else {
@@ -146,6 +167,9 @@ public class DataPermissionInterceptor extends BaseMultiTableInnerInterceptor im
 
     @Override
     public Expression buildTableExpression(final Table table, final Expression where, final String whereSegment) {
+        if (dataPermissionHandler == null) {
+            return null;
+        }
         // 只有新版数据权限处理器才会执行到这里
         final MultiDataPermissionHandler handler = (MultiDataPermissionHandler) dataPermissionHandler;
         return handler.getSqlSegment(table, where, whereSegment);

+ 38 - 18
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/H2UserTest.java

@@ -15,6 +15,37 @@
  */
 package com.baomidou.mybatisplus.test.h2;
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.apache.ibatis.exceptions.PersistenceException;
+import org.apache.ibatis.exceptions.TooManyResultsException;
+import org.apache.ibatis.plugin.Interceptor;
+import org.apache.ibatis.session.Configuration;
+import org.apache.ibatis.session.ResultHandler;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.RepeatedTest;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataAccessException;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.transaction.annotation.Transactional;
+
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@@ -35,26 +66,9 @@ import com.baomidou.mybatisplus.test.h2.entity.H2User;
 import com.baomidou.mybatisplus.test.h2.enums.AgeEnum;
 import com.baomidou.mybatisplus.test.h2.mapper.H2StudentMapper;
 import com.baomidou.mybatisplus.test.h2.service.IH2UserService;
+
 import net.sf.jsqlparser.parser.CCJSqlParserUtil;
 import net.sf.jsqlparser.statement.select.Select;
-import org.apache.ibatis.exceptions.PersistenceException;
-import org.apache.ibatis.exceptions.TooManyResultsException;
-import org.apache.ibatis.plugin.Interceptor;
-import org.apache.ibatis.session.Configuration;
-import org.apache.ibatis.session.ResultHandler;
-import org.apache.ibatis.session.SqlSessionFactory;
-import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;
-import org.junit.jupiter.api.*;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.dao.DataAccessException;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit.jupiter.SpringExtension;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.math.BigDecimal;
-import java.math.RoundingMode;
-import java.util.*;
 
 /**
  * Mybatis Plus H2 Junit Test
@@ -209,6 +223,12 @@ class H2UserTest extends BaseTest {
         userDB = userService.getById(id);
         Assertions.assertEquals(2, userDB.getVersion().intValue());
         Assertions.assertEquals("992", userDB.getName());
+        userService.lambdaUpdate().set(H2User::getAge,AgeEnum.THREE).eq(H2User::getTestId,id).update();
+        UpdateWrapper<H2User> wp = new UpdateWrapper<>();
+        wp.set("age",AgeEnum.TWO).eq("test_id",id);
+        wp.set("name", "yanjinyin@gitee");
+        userService.update(wp);
+
     }
 
     @Test