Parcourir la source

changelog-temp

miemie il y a 2 ans
Parent
commit
0675f31b71

+ 15 - 6
changelog-temp.md

@@ -1,7 +1,16 @@
 - 多租户插件:多表join表名必需起别名,否则追加的过滤条件不带前缀
-- fix: InterceptorIgnore 不能过滤 selectKey 的问题
-- fix: 补全`mybatis-plus-boot-starter-test`遗漏配置
-- feat: 分页新增informix数据库支持
-- feat: 支持spring-boot 2.7以上版本
-- feat: 雪花id新增反解时间戳方法`Sequence#parseIdTimestamp`
-- feat: BaseMapper.selectCount生成语句加入中`AS total`
+- InterceptorIgnore 不能过滤 selectKey 的问题
+- 分页新增`informix数据库`支持
+- 分页新增`优炫数据库`支持
+- 分页新增`TDengine数据库`支持
+- 分页新增`亚马逊redshift数据库`支持
+- 支持spring-boot 2.7以上版本
+- 雪花id新增反解时间戳方法`Sequence#parseIdTimestamp`
+- BaseMapper.selectCount生成语句加入中`AS total`
+- 修复IllegalSQLInnerInterceptor类ClassCastException异常,并优化日志
+- 移除注解`OrderBy`的过时属性`isDesc`
+- 移除`TableInfo`过时方法
+- 加入`JoinTableInfoInitHandler`类参与`TableInfo`初始化
+- 修复StringUtils.sqlInjectionReplaceBlank方法过滤sql不全,可能会导致sql注入的情况
+- 增加IService.lambdaQuery(entity)支持,写法更便捷
+- 新增数据变更记录(数据审计)插件`DataChangeRecorderInnerInterceptor`

+ 179 - 207
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DataChangeRecorderInterceptor.java → mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DataChangeRecorderInnerInterceptor.java

@@ -1,45 +1,8 @@
 package com.baomidou.mybatisplus.extension.plugins.inner;
 
-import static com.baomidou.mybatisplus.extension.plugins.inner.DataChangeRecorderInterceptor.convertDoubleQuotes;
-
-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.plugin.Intercepts;
-import org.apache.ibatis.plugin.Signature;
-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.core.metadata.TableInfo;
 import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
 import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
-
 import lombok.Data;
 import net.sf.jsqlparser.expression.Expression;
 import net.sf.jsqlparser.expression.JdbcParameter;
@@ -49,13 +12,26 @@ 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.AllColumns;
-import net.sf.jsqlparser.statement.select.PlainSelect;
-import net.sf.jsqlparser.statement.select.Select;
-import net.sf.jsqlparser.statement.select.SelectExpressionItem;
-import net.sf.jsqlparser.statement.select.SelectItem;
+import net.sf.jsqlparser.statement.select.*;
 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.reflection.SystemMetaObject;
+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;
 
 /**
  * <p>
@@ -63,51 +39,46 @@ import net.sf.jsqlparser.statement.update.UpdateSet;
  * 默认会生成一条log,格式:
  * ----------------------INSERT LOG------------------------------
  * {
- *   "tableName": "h2user",
- *   "operation": "insert",
- *   "recordStatus": "true",
- *   "changedData": [
- *     {
- *       "LAST_UPDATED_DT": "null->2022-08-22 18:49:16.512",
- *       "TEST_ID": "null->1561666810058739714",
- *       "AGE": "null->THREE"
- *     }
- *   ],
- *   "cost(ms)": 0
+ * "tableName": "h2user",
+ * "operation": "insert",
+ * "recordStatus": "true",
+ * "changedData": [
+ * {
+ * "LAST_UPDATED_DT": "null->2022-08-22 18:49:16.512",
+ * "TEST_ID": "null->1561666810058739714",
+ * "AGE": "null->THREE"
+ * }
+ * ],
+ * "cost(ms)": 0
  * }
  * </p>
  * <p>
- *  * ----------------------UPDATE LOG------------------------------
- *
+ * * ----------------------UPDATE LOG------------------------------
+ * <p>
  * {
- *   "tableName": "h2user",
- *   "operation": "update",
- *   "recordStatus": "true",
- *   "changedData": [
- *     {
- *       "TEST_ID": "102",
- *       "AGE": "2->THREE",
- *       "FIRSTNAME": "DOU.HAO->{\"json\":\"abc\"}",
- *       "LAST_UPDATED_DT": "null->2022-08-22 18:49:16.512"
- *     }
- *   ],
- *   "cost(ms)": 0
+ * "tableName": "h2user",
+ * "operation": "update",
+ * "recordStatus": "true",
+ * "changedData": [
+ * {
+ * "TEST_ID": "102",
+ * "AGE": "2->THREE",
+ * "FIRSTNAME": "DOU.HAO->{\"json\":\"abc\"}",
+ * "LAST_UPDATED_DT": "null->2022-08-22 18:49:16.512"
+ * }
+ * ],
+ * "cost(ms)": 0
  * }
  * </p>
  *
  * @author yuxiaobin
  * @date 2022-8-21
  */
-@Intercepts({
-    @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
-})
-public class DataChangeRecorderInterceptor implements InnerInterceptor {
-
+public class DataChangeRecorderInnerInterceptor implements InnerInterceptor {
+    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
     @SuppressWarnings("unused")
     public static final String IGNORED_TABLE_COLUMN_PROPERTIES = "ignoredTableColumns";
 
-    private final Logger logger = LoggerFactory.getLogger("DataChangeRecorder");
-
     private final Map<String, Set<String>> ignoredTableColumns = new ConcurrentHashMap<>();
     private final Set<String> ignoreAllColumns = new HashSet<>();//全部表的这些字段名,INSERT/UPDATE都忽略,delete暂时保留
 
@@ -515,13 +486,6 @@ public class DataChangeRecorderInterceptor implements InnerInterceptor {
         }
     }
 
-    public static String convertDoubleQuotes(Object obj) {
-        if (obj == null) {
-            return null;
-        }
-        return obj.toString().replace("\"", "\\\"");
-    }
-
     @Data
     public static class OperationResult {
 
@@ -585,160 +549,168 @@ public class DataChangeRecorderInterceptor implements InnerInterceptor {
             sb.append("}");
             return sb.toString();
         }
-
     }
 
-}
-
-
-@Data
-class Columns2SelectItemsResult {
+    @Data
+    public static class Columns2SelectItemsResult {
 
-    private Column pk;
-    /**
-     * all column with additional columns: ID, etc.
-     */
-    private List<SelectItem> selectItems;
-    /**
-     * newly added column count from meta data.
-     */
-    private int additionalItemCount;
+        private Column pk;
+        /**
+         * all column with additional columns: ID, etc.
+         */
+        private List<SelectItem> selectItems;
+        /**
+         * newly added column count from meta data.
+         */
+        private int additionalItemCount;
 
-    public static Columns2SelectItemsResult build(List<SelectItem> selectItems, int additionalItemCount) {
-        Columns2SelectItemsResult result = new Columns2SelectItemsResult();
-        result.setSelectItems(selectItems);
-        result.setAdditionalItemCount(additionalItemCount);
-        return result;
+        public static Columns2SelectItemsResult build(List<SelectItem> selectItems, int additionalItemCount) {
+            Columns2SelectItemsResult result = new Columns2SelectItemsResult();
+            result.setSelectItems(selectItems);
+            result.setAdditionalItemCount(additionalItemCount);
+            return result;
+        }
     }
 
-}
+    @Data
+    public static class OriginalDataObj {
 
-@Data
-class OriginalDataObj {
+        private List<DataChangedRecord> originalDataObj;
 
-    private List<DataChangedRecord> originalDataObj;
+        public boolean isEmpty() {
+            return originalDataObj == null || originalDataObj.isEmpty();
+        }
 
-    public boolean isEmpty() {
-        return originalDataObj == null || originalDataObj.isEmpty();
     }
 
-}
-
-@Data
-class DataColumnChangeResult {
-
-    private String columnName;
-    private Object originalValue;
-    private Object updateValue;
-
-    @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;
+    @Data
+    public static class DataColumnChangeResult {
+
+        private String columnName;
+        private Object originalValue;
+        private Object updateValue;
+
+        @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 Clob) {
+                    String originalStr = convertClob((Clob) originalValue);
+                    setOriginalValue(originalStr);
+                    return !originalStr.equals(updateValue);
+                }
+                return true;
             }
-            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;
+                return original.compareTo(update) != 0;
             }
-            return true;
+            return false;
         }
-        if (originalValue instanceof Comparable) {
-            Comparable original = (Comparable) originalValue;
-            Comparable update = (Comparable) updateValue;
-            return original.compareTo(update) != 0;
-        }
-        return false;
-    }
 
-    public static String convertClob(Clob clobObj) {
-        try {
-            return clobObj.getSubString(0, (int) clobObj.length());
-        } catch (Exception e) {
-            try (Reader is = clobObj.getCharacterStream()) {
-                char[] chars = new char[64];
-                int readChars;
-                StringBuilder sb = new StringBuilder();
-                while ((readChars = is.read(chars)) != -1) {
-                    sb.append(chars, 0, readChars);
+        public static String convertClob(Clob clobObj) {
+            try {
+                return clobObj.getSubString(0, (int) clobObj.length());
+            } catch (Exception e) {
+                try (Reader is = clobObj.getCharacterStream()) {
+                    char[] chars = new char[64];
+                    int readChars;
+                    StringBuilder sb = new StringBuilder();
+                    while ((readChars = is.read(chars)) != -1) {
+                        sb.append(chars, 0, readChars);
+                    }
+                    return sb.toString();
+                } catch (Exception e2) {
+                    //ignored
+                    return "unknown clobObj";
                 }
-                return sb.toString();
-            } catch (Exception e2) {
-                //ignored
-                return "unknown clobObj";
             }
         }
-    }
 
-    public static DataColumnChangeResult constrcutByUpdateVal(String columnName, Object updateValue) {
-        DataColumnChangeResult res = new DataColumnChangeResult();
-        res.setColumnName(columnName);
-        res.setUpdateValue(updateValue);
-        return res;
-    }
+        public static DataColumnChangeResult constrcutByUpdateVal(String columnName, Object updateValue) {
+            DataColumnChangeResult res = new DataColumnChangeResult();
+            res.setColumnName(columnName);
+            res.setUpdateValue(updateValue);
+            return res;
+        }
 
-    public static DataColumnChangeResult constrcutByOriginalVal(String columnName, Object originalValue) {
-        DataColumnChangeResult res = new DataColumnChangeResult();
-        res.setColumnName(columnName);
-        res.setOriginalValue(originalValue);
-        return res;
-    }
+        public static DataColumnChangeResult constrcutByOriginalVal(String columnName, Object originalValue) {
+            DataColumnChangeResult res = new DataColumnChangeResult();
+            res.setColumnName(columnName);
+            res.setOriginalValue(originalValue);
+            return res;
+        }
 
-    public String generateDataStr() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("\"").append(columnName).append("\"").append(":").append("\"").append(convertDoubleQuotes(originalValue)).append("->").append(convertDoubleQuotes(updateValue)).append("\"").append(",");
-        return sb.toString();
+        public String generateDataStr() {
+            StringBuilder sb = new StringBuilder();
+            sb.append("\"").append(columnName).append("\"").append(":").append("\"").append(convertDoubleQuotes(originalValue)).append("->").append(convertDoubleQuotes(updateValue)).append("\"").append(",");
+            return sb.toString();
+        }
+
+        public String convertDoubleQuotes(Object obj) {
+            if (obj == null) {
+                return null;
+            }
+            return obj.toString().replace("\"", "\\\"");
+        }
     }
-}
 
-@Data
-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) {
-        if (originalColumnDatas == null) {
-            return true;
-        }
-        boolean hasUpdate = false;
-        updatedColumns = new ArrayList<>(originalColumnDatas.size());
-        for (DataColumnChangeResult originalColumn : originalColumnDatas) {
-            final String columnName = originalColumn.getColumnName().toUpperCase();
-            if (ignoredColumns != null && ignoredColumns.contains(columnName) || ignoreAllColumns.contains(columnName)) {
-                continue;
+    @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) {
+            if (originalColumnDatas == null) {
+                return true;
             }
-            Object updatedValue = columnNameValMap.get(columnName);
-            if (originalColumn.isDataChanged(updatedValue)) {
-                hasUpdate = true;
-                originalColumn.setUpdateValue(updatedValue);
-                updatedColumns.add(originalColumn);
+            boolean hasUpdate = false;
+            updatedColumns = new ArrayList<>(originalColumnDatas.size());
+            for (DataColumnChangeResult originalColumn : originalColumnDatas) {
+                final String columnName = originalColumn.getColumnName().toUpperCase();
+                if (ignoredColumns != null && ignoredColumns.contains(columnName) || ignoreAllColumns.contains(columnName)) {
+                    continue;
+                }
+                Object updatedValue = columnNameValMap.get(columnName);
+                if (originalColumn.isDataChanged(updatedValue)) {
+                    hasUpdate = true;
+                    originalColumn.setUpdateValue(updatedValue);
+                    updatedColumns.add(originalColumn);
+                }
             }
+            return hasUpdate;
         }
-        return hasUpdate;
-    }
 
-    public String generateUpdatedDataStr() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("{");
-        if (pkColumnName != null) {
-            sb.append("\"").append(pkColumnName).append("\"").append(":").append("\"").append(convertDoubleQuotes(pkColumnVal)).append("\"").append(",");
+        public String generateUpdatedDataStr() {
+            StringBuilder sb = new StringBuilder();
+            sb.append("{");
+            if (pkColumnName != null) {
+                sb.append("\"").append(pkColumnName).append("\"").append(":").append("\"").append(convertDoubleQuotes(pkColumnVal)).append("\"").append(",");
+            }
+            for (DataColumnChangeResult update : updatedColumns) {
+                sb.append(update.generateDataStr());
+            }
+            sb.replace(sb.length() - 1, sb.length(), "}");
+            return sb.toString();
         }
-        for (DataColumnChangeResult update : updatedColumns) {
-            sb.append(update.generateDataStr());
+
+        public String convertDoubleQuotes(Object obj) {
+            if (obj == null) {
+                return null;
+            }
+            return obj.toString().replace("\"", "\\\"");
         }
-        sb.replace(sb.length() - 1, sb.length(), "}");
-        return sb.toString();
     }
-
-
 }

+ 12 - 14
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/config/MybatisPlusConfig.java

@@ -15,18 +15,6 @@
  */
 package com.baomidou.mybatisplus.test.h2.config;
 
-import java.util.List;
-
-import javax.sql.DataSource;
-
-import org.apache.ibatis.session.ExecutorType;
-import org.apache.ibatis.session.SqlSessionFactory;
-import org.apache.ibatis.type.EnumOrdinalTypeHandler;
-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.FieldFill;
 import com.baomidou.mybatisplus.core.MybatisConfiguration;
 import com.baomidou.mybatisplus.core.config.GlobalConfig;
@@ -36,11 +24,21 @@ import com.baomidou.mybatisplus.core.metadata.TableInfo;
 import com.baomidou.mybatisplus.extension.injector.methods.AlwaysUpdateSomeColumnById;
 import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;
 import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
-import com.baomidou.mybatisplus.extension.plugins.inner.DataChangeRecorderInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.DataChangeRecorderInnerInterceptor;
 import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
 import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
 import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
 import com.baomidou.mybatisplus.test.h2.H2MetaObjectHandler;
+import org.apache.ibatis.session.ExecutorType;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.apache.ibatis.type.EnumOrdinalTypeHandler;
+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;
+import java.util.List;
 
 /**
  * Mybatis Plus Config
@@ -71,7 +69,7 @@ public class MybatisPlusConfig {
         mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
         // mybatisPlusInterceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
         mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
-        mybatisPlusInterceptor.addInnerInterceptor(new DataChangeRecorderInterceptor());
+        mybatisPlusInterceptor.addInnerInterceptor(new DataChangeRecorderInnerInterceptor());
         sqlSessionFactory.setPlugins(mybatisPlusInterceptor);
 
         globalConfig.setMetaObjectHandler(new H2MetaObjectHandler());