From f6cc89c00bd05d67eb809869297789c5440a436f Mon Sep 17 00:00:00 2001 From: yuxiaobin <179634696@qq.com> Date: Fri, 29 Mar 2024 12:20:20 +0800 Subject: [PATCH 1/2] fix: I9C3P4@gitee --- .../DataChangeRecorderInnerInterceptor.java | 127 +++++++++++------- .../mybatisplus/test/h2/H2UserTest.java | 20 ++- .../mybatisplus/test/h2/entity/H2User.java | 11 +- .../src/test/resources/h2/user.ddl.sql | 1 + 4 files changed, 106 insertions(+), 53 deletions(-) diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DataChangeRecorderInnerInterceptor.java b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DataChangeRecorderInnerInterceptor.java index 2db2c3ec7..d6d1db61d 100644 --- a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DataChangeRecorderInnerInterceptor.java +++ b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DataChangeRecorderInnerInterceptor.java @@ -16,7 +16,6 @@ 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; @@ -25,13 +24,13 @@ 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.Optional; import java.util.Properties; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -51,6 +50,7 @@ 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.handlers.MybatisEnumTypeHandler; import com.baomidou.mybatisplus.core.metadata.TableFieldInfo; import com.baomidou.mybatisplus.core.metadata.TableInfo; import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; @@ -199,7 +199,8 @@ public class DataChangeRecorderInnerInterceptor implements InnerInterceptor { result.setOperation("insert"); result.setTableName(insertStmt.getTable().getName()); result.setRecordStatus(true); - result.buildDataStr(compareAndGetUpdatedColumnDatas(result.getTableName(), boundSql, insertStmt, null)); + Map updatedColumnDatas = getUpdatedColumnDatas(result.getTableName(), boundSql, insertStmt); + result.buildDataStr(compareAndGetUpdatedColumnDatas(result.getTableName(), boundSql, insertStmt, null, updatedColumnDatas)); return result; } @@ -238,15 +239,25 @@ public class DataChangeRecorderInnerInterceptor implements InnerInterceptor { boundSql4Select.setAdditionalParameter(ety.getKey(), ety.getValue()); } } - OriginalDataObj originalData = buildOriginalObjectData(selectStmt, buildColumns2SelectItems.getPk(), mappedStatement, boundSql4Select, connection); + Map updatedColumnDatas = getUpdatedColumnDatas(table.getName(), boundSql, updateStmt); + OriginalDataObj originalData = buildOriginalObjectData(updatedColumnDatas, selectStmt, buildColumns2SelectItems.getPk(), mappedStatement, boundSql4Select, connection); OperationResult result = new OperationResult(); result.setOperation("update"); result.setTableName(table.getName()); result.setRecordStatus(true); - result.buildDataStr(compareAndGetUpdatedColumnDatas(result.getTableName(), boundSql, updateStmt, originalData)); + result.buildDataStr(compareAndGetUpdatedColumnDatas(result.getTableName(), boundSql, updateStmt, originalData, updatedColumnDatas)); return result; } + private TableInfo getTableInfoByTableName(String tableName) { + for (TableInfo tableInfo : TableInfoHelper.getTableInfos()) { + if (tableName.equalsIgnoreCase(tableInfo.getTableName())) { + return tableInfo; + } + } + return null; + } + /** * 将update SET部分的jdbc参数去除 * @@ -268,13 +279,8 @@ public class DataChangeRecorderInnerInterceptor implements InnerInterceptor { return originalMappingList.subList(removeParamCount, originalMappingList.size()); } - /** - * @param updateSql - * @param originalDataObj - * @return - */ - private List compareAndGetUpdatedColumnDatas(String tableName, BoundSql updateSql, Statement statement, OriginalDataObj originalDataObj) { - Map columnNameValMap = new HashMap<>(updateSql.getParameterMappings().size()); + protected Map getUpdatedColumnDatas(String tableName, BoundSql updateSql, Statement statement) { + Map columnNameValMap = new HashMap<>(updateSql.getParameterMappings().size()); Map columnSetIndexMap = new HashMap<>(updateSql.getParameterMappings().size()); List selectItemsFromUpdateSql = new ArrayList<>(); if (statement instanceof Update) { @@ -315,12 +321,17 @@ public class DataChangeRecorderInnerInterceptor implements InnerInterceptor { 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)); + Object valObj = metaObject.getValue(propertyName); + if (valObj instanceof IEnum) { + valObj = ((IEnum) valObj).getValue(); + } else if (valObj instanceof Enum) { + valObj = getEnumValue((Enum) valObj); + } if (columnNameValMap.containsKey(colkey)) { - columnNameValMap.put(relatedColumnsUpperCaseWithoutUnderline.get(propertyNameTrim), String.valueOf(columnNameValMap.get(colkey)).replace("?", val)); + columnNameValMap.put(relatedColumnsUpperCaseWithoutUnderline.get(propertyNameTrim), String.valueOf(columnNameValMap.get(colkey)).replace("?", valObj == null ? "" : valObj.toString())); } if (columnName != null && !columnNameValMap.containsKey(columnName)) { - columnNameValMap.put(columnName, val); + columnNameValMap.put(columnName, valObj); } } else { if (columnName != null) { @@ -332,12 +343,20 @@ public class DataChangeRecorderInnerInterceptor implements InnerInterceptor { } } dealWithUpdateWrapper(columnSetIndexMap, columnNameValMap, updateSql); + return columnNameValMap; + } + /** + * @param updateSql + * @param originalDataObj + * @return + */ + private List compareAndGetUpdatedColumnDatas(String tableName, BoundSql updateSql, Statement statement, OriginalDataObj originalDataObj, Map columnNameValMap) { final Set ignoredColumns = ignoredTableColumns.get(tableName.toUpperCase()); if (originalDataObj == null || originalDataObj.isEmpty()) { DataChangedRecord oneRecord = new DataChangedRecord(); List updateColumns = new ArrayList<>(columnNameValMap.size()); - for (Map.Entry ety : columnNameValMap.entrySet()) { + for (Map.Entry ety : columnNameValMap.entrySet()) { String columnName = ety.getKey(); if ((ignoredColumns == null || !ignoredColumns.contains(columnName)) && !ignoreAllColumns.contains(columnName)) { updateColumns.add(DataColumnChangeResult.constrcutByUpdateVal(columnName, ety.getValue())); @@ -357,8 +376,17 @@ public class DataChangeRecorderInnerInterceptor implements InnerInterceptor { return updateDataList; } + private Object getEnumValue(Enum enumVal) { + Optional enumValueFieldName = MybatisEnumTypeHandler.findEnumValueFieldName(enumVal.getClass()); + if (enumValueFieldName.isPresent()) { + return SystemMetaObject.forObject(enumVal).getValue(enumValueFieldName.get()); + } + return enumVal; + + } + @SuppressWarnings("rawtypes") - private void dealWithUpdateWrapper(Map columnSetIndexMap, Map columnNameValMap, BoundSql updateSql){ + private void dealWithUpdateWrapper(Map columnSetIndexMap, Map columnNameValMap, BoundSql updateSql) { if (columnSetIndexMap.size() <= columnNameValMap.size()) { return; } @@ -507,20 +535,21 @@ public class DataChangeRecorderInnerInterceptor implements InnerInterceptor { } } - private OriginalDataObj buildOriginalObjectData(Select selectStmt, Column pk, MappedStatement mappedStatement, BoundSql boundSql, Connection connection) { + private OriginalDataObj buildOriginalObjectData(Map updatedColumnDatas, Select selectStmt, Column pk, MappedStatement mappedStatement, BoundSql boundSql, Connection connection) { try (PreparedStatement statement = connection.prepareStatement(selectStmt.toString())) { DefaultParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, boundSql.getParameterObject(), boundSql); parameterHandler.setParameters(statement); ResultSet resultSet = statement.executeQuery(); List originalObjectDatas = new LinkedList<>(); int count = 0; + while (resultSet.next()) { ++count; if (checkTableBatchLimitExceeded(selectStmt, count)) { logger.error("batch update limit exceed: count={}, BATCH_UPDATE_LIMIT={}", count, BATCH_UPDATE_LIMIT); throw DataUpdateLimitationException.DEFAULT; } - originalObjectDatas.add(prepareOriginalDataObj(resultSet, pk)); + originalObjectDatas.add(prepareOriginalDataObj(updatedColumnDatas, resultSet, pk)); } OriginalDataObj result = new OriginalDataObj(); result.setOriginalDataObj(originalObjectDatas); @@ -580,14 +609,20 @@ public class DataChangeRecorderInnerInterceptor implements InnerInterceptor { * @return * @throws SQLException */ - private DataChangedRecord prepareOriginalDataObj(ResultSet resultSet, Column pk) throws SQLException { + private DataChangedRecord prepareOriginalDataObj(Map updatedColumnDatas, ResultSet resultSet, Column pk) throws SQLException { final ResultSetMetaData metaData = resultSet.getMetaData(); int columnCount = metaData.getColumnCount(); List originalColumnDatas = new LinkedList<>(); DataColumnChangeResult pkval = null; for (int i = 1; i <= columnCount; ++i) { String columnName = metaData.getColumnName(i).toUpperCase(); - DataColumnChangeResult col = DataColumnChangeResult.constrcutByOriginalVal(columnName, resultSet.getObject(i)); + DataColumnChangeResult col; + Object updateVal = updatedColumnDatas.get(columnName); + if (updateVal != null && updateVal.getClass().getCanonicalName().startsWith("java.")) { + col = DataColumnChangeResult.constrcutByOriginalVal(columnName, resultSet.getObject(i, updateVal.getClass())); + } else { + col = DataColumnChangeResult.constrcutByOriginalVal(columnName, resultSet.getObject(i)); + } if (pk != null && columnName.equalsIgnoreCase(pk.getColumnName())) { pkval = col; } else { @@ -603,6 +638,7 @@ public class DataChangeRecorderInnerInterceptor implements InnerInterceptor { return changedRecord; } + private Columns2SelectItemsResult buildColumns2SelectItems(String tableName, List columns) { if (columns == null || columns.isEmpty()) { return Columns2SelectItemsResult.build(Collections.singletonList(new AllColumns()), 0); @@ -611,16 +647,15 @@ public class DataChangeRecorderInnerInterceptor implements InnerInterceptor { for (Column column : columns) { selectItems.add(new SelectExpressionItem(column)); } - for (TableInfo tableInfo : TableInfoHelper.getTableInfos()) { - if (tableName.equalsIgnoreCase(tableInfo.getTableName())) { - Column pk = new Column(tableInfo.getKeyColumn()); - selectItems.add(new SelectExpressionItem(pk)); - Columns2SelectItemsResult result = Columns2SelectItemsResult.build(selectItems, 1); - result.setPk(pk); - return result; - } + TableInfo tableInfo = getTableInfoByTableName(tableName); + if (tableInfo == null) { + return Columns2SelectItemsResult.build(selectItems, 0); } - return Columns2SelectItemsResult.build(selectItems, 0); + Column pk = new Column(tableInfo.getKeyColumn()); + selectItems.add(new SelectExpressionItem(pk)); + Columns2SelectItemsResult result = Columns2SelectItemsResult.build(selectItems, 1); + result.setPk(pk); + return result; } private String buildParameterObject(BoundSql boundSql) { @@ -815,15 +850,22 @@ public class DataChangeRecorderInnerInterceptor implements InnerInterceptor { @SuppressWarnings("rawtypes") public boolean isDataChanged(Object updateValue) { if (!Objects.equals(originalValue, updateValue)) { - if (updateValue instanceof Number && originalValue instanceof Number) { - BigDecimal update = new BigDecimal(updateValue.toString()); - BigDecimal original = new BigDecimal(originalValue.toString()); - return update.compareTo(original) != 0; - } - if (updateValue instanceof Date && originalValue instanceof Date) { - Date update = (Date) updateValue; - Date original = (Date) originalValue; - return update.compareTo(original) != 0; +// if (originalValue instanceof Number) { +// BigDecimal update = new BigDecimal(updateValue.toString()); +// BigDecimal original = new BigDecimal(originalValue.toString()); +// return update.compareTo(original) != 0; +// } +// if (originalValue instanceof Date) { +// return ((Date) originalValue).compareTo((Date) updateValue)!=0; +// } + if (originalValue instanceof Comparable) { + Comparable original = (Comparable) originalValue; + Comparable update = (Comparable) updateValue; + try { + return update == null || original.compareTo(update) != 0; + } catch (Exception e) { + return true; + } } if (originalValue instanceof Clob) { String originalStr = convertClob((Clob) originalValue); @@ -832,11 +874,6 @@ public class DataChangeRecorderInnerInterceptor implements InnerInterceptor { } return true; } - if (originalValue instanceof Comparable) { - Comparable original = (Comparable) originalValue; - Comparable update = (Comparable) updateValue; - return original.compareTo(update) != 0; - } return false; } @@ -895,7 +932,7 @@ public class DataChangeRecorderInnerInterceptor implements InnerInterceptor { private List originalColumnDatas; private List updatedColumns; - public boolean hasUpdate(Map columnNameValMap, Set ignoredColumns, Set ignoreAllColumns) { + public boolean hasUpdate(Map columnNameValMap, Set ignoredColumns, Set ignoreAllColumns) { if (originalColumnDatas == null) { return true; } diff --git a/mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/H2UserTest.java b/mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/H2UserTest.java index 0e22d4b84..10f8ca577 100644 --- a/mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/H2UserTest.java +++ b/mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/H2UserTest.java @@ -17,6 +17,7 @@ package com.baomidou.mybatisplus.test.h2; import java.math.BigDecimal; import java.math.RoundingMode; +import java.time.LocalDateTime; import java.util.AbstractList; import java.util.ArrayList; import java.util.Arrays; @@ -211,21 +212,29 @@ class H2UserTest extends BaseTest { user.setDesc("asdf"); user.setTestType(1); user.setVersion(1); + final LocalDateTime dateTime = LocalDateTime.of(2024, 3, 29, 10, 0, 0); + user.setCreatedDt(dateTime); userService.save(user); H2User userDB = userService.getById(id); Assertions.assertEquals(1, userDB.getVersion().intValue()); + Assertions.assertTrue(userDB.getCreatedDt().compareTo(dateTime) == 0); userDB.setName("992"); + userDB.setCreatedDt(dateTime); + System.out.println("==============================================="); userService.updateById(userDB); Assertions.assertEquals(2, userDB.getVersion().intValue(), "updated version value should be updated to entity"); 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(); + userDB.setCreatedDt(LocalDateTime.now()); + userService.updateById(userDB); + System.out.println("==============================================="); + userService.lambdaUpdate().set(H2User::getAge, AgeEnum.THREE).eq(H2User::getTestId, id).update(); UpdateWrapper wp = new UpdateWrapper<>(); - wp.set("age",AgeEnum.TWO).eq("test_id",id); + wp.set("age", AgeEnum.TWO).eq("test_id", id); wp.set("name", "yanjinyin@gitee"); userService.update(wp); @@ -515,12 +524,10 @@ class H2UserTest extends BaseTest { final Select select = (Select) CCJSqlParserUtil.parse(targetSql1); Assertions.assertEquals(select.toString(), targetSql1); - final String targetSql2 = "SELECT * FROM user WHERE id NOT IN (?)"; final Select select2 = (Select) CCJSqlParserUtil.parse(targetSql2); Assertions.assertEquals(select2.toString(), targetSql2); - final String targetSql3 = "SELECT * FROM user WHERE id IS NOT NULL"; final Select select3 = (Select) CCJSqlParserUtil.parse(targetSql3); Assertions.assertEquals(select3.toString(), targetSql3); @@ -876,16 +883,19 @@ class H2UserTest extends BaseTest { System.out.println("-------处理OrderByDesc----------"); return super.doOrderByDesc(condition, column, columns); } + @Override - protected LambdaQueryChainWrapper doOrderByAsc(boolean condition, SFunction column, List> columns) { + protected LambdaQueryChainWrapper doOrderByAsc(boolean condition, SFunction column, List> columns) { System.out.println("-------处理OrderByAsc----------"); return super.doOrderByAsc(condition, column, columns); } + @Override protected LambdaQueryChainWrapper doOrderBy(boolean condition, boolean isAsc, SFunction column, List> columns) { System.out.println("-------处理OrderBy----------"); return super.doOrderBy(condition, isAsc, column, columns); } + @Override protected LambdaQueryChainWrapper doGroupBy(boolean condition, SFunction column, List> columns) { System.out.println("-------处理GroupBy----------"); diff --git a/mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/entity/H2User.java b/mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/entity/H2User.java index 7b9cae4ea..839e5026a 100644 --- a/mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/entity/H2User.java +++ b/mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/entity/H2User.java @@ -15,19 +15,21 @@ */ package com.baomidou.mybatisplus.test.h2.entity; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.Date; + 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 com.baomidou.mybatisplus.annotation.Version; import com.baomidou.mybatisplus.test.h2.enums.AgeEnum; + import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; -import java.math.BigDecimal; -import java.util.Date; - /** * 测试用户类 * @@ -75,6 +77,9 @@ public class H2User extends SuperEntity { @TableLogic private Integer deleted; + @TableField("created_dt") + private LocalDateTime createdDt; + public H2User() { diff --git a/mybatis-plus/src/test/resources/h2/user.ddl.sql b/mybatis-plus/src/test/resources/h2/user.ddl.sql index 881359e95..6e03c102d 100644 --- a/mybatis-plus/src/test/resources/h2/user.ddl.sql +++ b/mybatis-plus/src/test/resources/h2/user.ddl.sql @@ -7,6 +7,7 @@ CREATE TABLE IF NOT EXISTS h2user ( price DECIMAL(10,2) NULL DEFAULT NULL, desc VARCHAR(30) NULL DEFAULT NULL , version INT(5) NULL DEFAULT NULL, + created_dt TIMESTAMP NULL, last_updated_dt TIMESTAMP NULL, deleted INT(1) NULL DEFAULT 0 , PRIMARY KEY (test_id) -- Gitee From d75957d59867c6f097a80030c36f57c19973e71e Mon Sep 17 00:00:00 2001 From: yuxiaobin <179634696@qq.com> Date: Fri, 29 Mar 2024 12:23:12 +0800 Subject: [PATCH 2/2] fix: I9C3P4@gitee --- .../DataChangeRecorderInnerInterceptor.java | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DataChangeRecorderInnerInterceptor.java b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DataChangeRecorderInnerInterceptor.java index d6d1db61d..5fae3ae88 100644 --- a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DataChangeRecorderInnerInterceptor.java +++ b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DataChangeRecorderInnerInterceptor.java @@ -850,14 +850,11 @@ public class DataChangeRecorderInnerInterceptor implements InnerInterceptor { @SuppressWarnings("rawtypes") public boolean isDataChanged(Object updateValue) { if (!Objects.equals(originalValue, updateValue)) { -// if (originalValue instanceof Number) { -// BigDecimal update = new BigDecimal(updateValue.toString()); -// BigDecimal original = new BigDecimal(originalValue.toString()); -// return update.compareTo(original) != 0; -// } -// if (originalValue instanceof Date) { -// return ((Date) originalValue).compareTo((Date) updateValue)!=0; -// } + if (originalValue instanceof Clob) { + String originalStr = convertClob((Clob) originalValue); + setOriginalValue(originalStr); + return !originalStr.equals(updateValue); + } if (originalValue instanceof Comparable) { Comparable original = (Comparable) originalValue; Comparable update = (Comparable) updateValue; @@ -867,11 +864,6 @@ public class DataChangeRecorderInnerInterceptor implements InnerInterceptor { return true; } } - if (originalValue instanceof Clob) { - String originalStr = convertClob((Clob) originalValue); - setOriginalValue(originalStr); - return !originalStr.equals(updateValue); - } return true; } return false; -- Gitee