Sfoglia il codice sorgente

自定义mapper方法逻辑优化

woody 1 anno fa
parent
commit
e1eb820430

+ 1 - 1
framework-boot/pom.xml

@@ -69,7 +69,7 @@
                 <artifactId>apidoc-maven-plugin</artifactId>
                 <version>${apidoc-maven-plugin.version}</version>
                 <configuration>
-                    <includeHeaders>{String} scope 应用范围,{String} using 使用信息: NORMAL(常规使用)、NEWLY(当日首次使用)、INITIAL(历史首次使用),{String} device 设备标识,{String} channel 渠道来源,{String} platform 平台标识: PC(PC)、IOS(苹果)、ANDROID(安卓),{String} terminal 终端标识: WEB(Web)、APP(App)、APPLET(小程序),{String} version 终端版本,{Long} timestamp 请求时间戳,{String} signature 签名信息,{String} fingerprint 设备指纹,{String} authorization 认证信息</includeHeaders>
+                    <includeHeaders>{String} scope 应用范围,{String} using 使用信息: NORMAL(常规使用)、DAILY(当日首次使用)、INITIAL(历史首次使用),{String} device 设备标识,{String} channel 渠道来源,{String} platform 平台标识: PC(PC)、IOS(苹果)、ANDROID(安卓),{String} terminal 终端标识: WEB(Web)、APP(App)、APPLET(小程序),{String} version 终端版本,{Long} timestamp 请求时间戳,{String} signature 签名信息,{String} fingerprint 设备指纹,{String} authorization 认证信息</includeHeaders>
                     <excludeClasses>com.chelvc.framework.base.interceptor.GlobalExceptionInterceptor</excludeClasses>
                     <analyserFactoryClass>com.chelvc.framework.base.apidoc.MethodAnalyserFactory</analyserFactoryClass>
                 </configuration>

+ 1 - 1
framework-common/src/main/java/com/chelvc/framework/common/model/Using.java

@@ -18,7 +18,7 @@ public enum Using implements Enumerable {
     /**
      * 当日首次使用
      */
-    NEWLY("当日首次使用"),
+    DAILY("当日首次使用"),
 
     /**
      * 历史首次使用

+ 54 - 0
framework-database/src/main/java/com/chelvc/framework/database/annotation/CreateUpdate.java

@@ -0,0 +1,54 @@
+package com.chelvc.framework.database.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 创建或者更新注解
+ *
+ * @author Woody
+ * @date 2024/3/5
+ */
+@Inherited
+@Documented
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface CreateUpdate {
+    /**
+     * 判断字段是否启用更新
+     *
+     * @return true/false
+     */
+    boolean enabled() default true;
+
+    /**
+     * 获取字段更新方式
+     *
+     * @return 更新方式
+     */
+    Mode mode() default Mode.REPLACE;
+
+    /**
+     * 更新方式枚举
+     */
+    enum Mode {
+        /**
+         * 替换
+         */
+        REPLACE,
+
+        /**
+         * 自增
+         */
+        INCREMENT,
+
+        /**
+         * 自减
+         */
+        DECREMENT;
+    }
+}

+ 3 - 0
framework-database/src/main/java/com/chelvc/framework/database/entity/CreateEntity.java

@@ -3,6 +3,7 @@ package com.chelvc.framework.database.entity;
 import java.io.Serializable;
 import java.util.Date;
 
+import com.chelvc.framework.database.annotation.CreateUpdate;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
@@ -22,10 +23,12 @@ public abstract class CreateEntity<ID extends Serializable> implements Creatable
     /**
      * 创建用户
      */
+    @CreateUpdate(enabled = false)
     private Long creator;
 
     /**
      * 创建时间
      */
+    @CreateUpdate(enabled = false)
     private Date createTime;
 }

+ 3 - 0
framework-database/src/main/java/com/chelvc/framework/database/entity/ModifyEntity.java

@@ -3,6 +3,7 @@ package com.chelvc.framework.database.entity;
 import java.io.Serializable;
 import java.util.Date;
 
+import com.chelvc.framework.database.annotation.CreateUpdate;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
@@ -22,11 +23,13 @@ public abstract class ModifyEntity<ID extends Serializable> implements Creatable
     /**
      * 创建用户
      */
+    @CreateUpdate(enabled = false)
     private Long creator;
 
     /**
      * 创建时间
      */
+    @CreateUpdate(enabled = false)
     private Date createTime;
 
     /**

+ 94 - 0
framework-database/src/main/java/com/chelvc/framework/database/mapper/AbstractInsertMethod.java

@@ -0,0 +1,94 @@
+package com.chelvc.framework.database.mapper;
+
+import java.util.List;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.core.enums.SqlMethod;
+import com.baomidou.mybatisplus.core.injector.AbstractMethod;
+import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
+import com.baomidou.mybatisplus.core.metadata.TableInfo;
+import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
+import com.chelvc.framework.common.util.StringUtils;
+import lombok.NonNull;
+import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
+import org.apache.ibatis.executor.keygen.KeyGenerator;
+import org.apache.ibatis.executor.keygen.NoKeyGenerator;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.mapping.SqlSource;
+
+/**
+ * 数据插入方法抽象实现
+ *
+ * @author Woody
+ * @date 2024/3/5
+ */
+public abstract class AbstractInsertMethod extends AbstractMethod {
+    /**
+     * 方法标识
+     */
+    protected final String id;
+
+    public AbstractInsertMethod(@NonNull String id) {
+        this.id = id;
+    }
+
+    /**
+     * 将字段转换成列
+     *
+     * @param table  表信息
+     * @param fields 字段列表
+     * @return 列信息
+     */
+    protected String field2column(TableInfo table, List<TableFieldInfo> fields) {
+        String columns = table.getKeyInsertSqlColumn(false) +
+                this.filterTableFieldInfo(fields, null, TableFieldInfo::getInsertSqlColumn, EMPTY);
+        return columns.substring(0, columns.length() - 1);
+    }
+
+    /**
+     * 将字段转换成属性
+     *
+     * @param table  表信息
+     * @param fields 字段列表
+     * @return 属性信息
+     */
+    protected String field2property(TableInfo table, List<TableFieldInfo> fields) {
+        String properties = table.getKeyInsertSqlProperty(null, false) +
+                this.filterTableFieldInfo(fields, null, i -> i.getInsertSqlProperty(null), EMPTY);
+        return properties.substring(0, properties.length() - 1);
+    }
+
+    /**
+     * 初始化方法脚本
+     *
+     * @param table 表信息
+     * @return 脚本信息
+     */
+    protected abstract String initializeMethodScript(TableInfo table);
+
+    @Override
+    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
+        String keyColumn = null;
+        String keyProperty = null;
+        KeyGenerator keyGenerator;
+        if (StringUtils.isEmpty(tableInfo.getKeyProperty())) {
+            keyGenerator = new NoKeyGenerator();
+        } else if (tableInfo.getIdType() == IdType.AUTO) {
+            keyColumn = tableInfo.getKeyColumn();
+            keyProperty = tableInfo.getKeyProperty();
+            keyGenerator = new Jdbc3KeyGenerator();
+        } else if (tableInfo.getKeySequence() != null) {
+            keyColumn = tableInfo.getKeyColumn();
+            keyProperty = tableInfo.getKeyProperty();
+            String method = this.getMethod(SqlMethod.INSERT_ONE);
+            keyGenerator = TableInfoHelper.genKeyGenerator(method, tableInfo, this.builderAssistant);
+        } else {
+            keyGenerator = new NoKeyGenerator();
+        }
+        String script = this.initializeMethodScript(tableInfo);
+        SqlSource source = this.languageDriver.createSqlSource(this.configuration, script, modelClass);
+        return this.addInsertMappedStatement(
+                mapperClass, modelClass, this.id, source, keyGenerator, keyProperty, keyColumn
+        );
+    }
+}

+ 13 - 41
framework-database/src/main/java/com/chelvc/framework/database/mapper/InsertIgnoreMethod.java

@@ -2,18 +2,9 @@ package com.chelvc.framework.database.mapper;
 
 import java.util.List;
 
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.core.enums.SqlMethod;
-import com.baomidou.mybatisplus.core.injector.AbstractMethod;
 import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
 import com.baomidou.mybatisplus.core.metadata.TableInfo;
-import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
-import com.chelvc.framework.common.util.StringUtils;
-import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
-import org.apache.ibatis.executor.keygen.KeyGenerator;
-import org.apache.ibatis.executor.keygen.NoKeyGenerator;
-import org.apache.ibatis.mapping.MappedStatement;
-import org.apache.ibatis.mapping.SqlSource;
+import lombok.NonNull;
 
 /**
  * 插入或忽略方法实现
@@ -21,38 +12,19 @@ import org.apache.ibatis.mapping.SqlSource;
  * @author Woody
  * @date 2024/2/27
  */
-public class InsertIgnoreMethod extends AbstractMethod {
+public class InsertIgnoreMethod extends AbstractInsertMethod {
+    public InsertIgnoreMethod() {
+        super("insertIgnore");
+    }
+
     @Override
-    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
-        String keyColumn = null;
-        String keyProperty = null;
-        KeyGenerator keyGenerator;
-        if (StringUtils.isEmpty(tableInfo.getKeyProperty())) {
-            keyGenerator = new NoKeyGenerator();
-        } else if (tableInfo.getIdType() == IdType.AUTO) {
-            keyColumn = tableInfo.getKeyColumn();
-            keyProperty = tableInfo.getKeyProperty();
-            keyGenerator = new Jdbc3KeyGenerator();
-        } else if (tableInfo.getKeySequence() != null) {
-            keyColumn = tableInfo.getKeyColumn();
-            keyProperty = tableInfo.getKeyProperty();
-            String method = this.getMethod(SqlMethod.INSERT_ONE);
-            keyGenerator = TableInfoHelper.genKeyGenerator(method, tableInfo, this.builderAssistant);
-        } else {
-            keyGenerator = new NoKeyGenerator();
-        }
-        List<TableFieldInfo> fields = tableInfo.getFieldList();
-        String columns = tableInfo.getKeyInsertSqlColumn(false) +
-                this.filterTableFieldInfo(fields, null, TableFieldInfo::getInsertSqlColumn, EMPTY);
-        columns = columns.substring(0, columns.length() - 1);
-        String properties = tableInfo.getKeyInsertSqlProperty(null, false) +
-                this.filterTableFieldInfo(fields, null, i -> i.getInsertSqlProperty(null), EMPTY);
-        properties = properties.substring(0, properties.length() - 1);
-        String script = String.format("<script>\nINSERT IGNORE INTO %s (%s) VALUES (%s)\n</script>",
-                tableInfo.getTableName(), columns, properties);
-        SqlSource source = this.languageDriver.createSqlSource(this.configuration, script, modelClass);
-        return this.addInsertMappedStatement(
-                mapperClass, modelClass, "insertIgnore", source, keyGenerator, keyProperty, keyColumn
+    protected String initializeMethodScript(@NonNull TableInfo table) {
+        List<TableFieldInfo> fields = table.getFieldList();
+        String columns = this.field2column(table, fields);
+        String properties = this.field2property(table, fields);
+        return String.format(
+                "<script>\nINSERT IGNORE INTO %s (%s) VALUES (%s)\n</script>",
+                table.getTableName(), columns, properties
         );
     }
 }

+ 32 - 43
framework-database/src/main/java/com/chelvc/framework/database/mapper/InsertUpdateMethod.java

@@ -1,20 +1,14 @@
 package com.chelvc.framework.database.mapper;
 
 import java.util.List;
+import java.util.stream.Collectors;
 
-import com.baomidou.mybatisplus.annotation.IdType;
-import com.baomidou.mybatisplus.core.enums.SqlMethod;
-import com.baomidou.mybatisplus.core.injector.AbstractMethod;
 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.StringPool;
 import com.chelvc.framework.common.util.StringUtils;
-import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
-import org.apache.ibatis.executor.keygen.KeyGenerator;
-import org.apache.ibatis.executor.keygen.NoKeyGenerator;
-import org.apache.ibatis.mapping.MappedStatement;
-import org.apache.ibatis.mapping.SqlSource;
+import com.chelvc.framework.database.annotation.CreateUpdate;
+import lombok.NonNull;
 
 /**
  * 插入或修改方法实现
@@ -22,42 +16,37 @@ import org.apache.ibatis.mapping.SqlSource;
  * @author Woody
  * @date 2024/2/27
  */
-public class InsertUpdateMethod extends AbstractMethod {
+public class InsertUpdateMethod extends AbstractInsertMethod {
+    public InsertUpdateMethod() {
+        super("insertUpdate");
+    }
+
     @Override
-    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
-        String keyColumn = null;
-        String keyProperty = null;
-        KeyGenerator keyGenerator;
-        if (StringUtils.isEmpty(tableInfo.getKeyProperty())) {
-            keyGenerator = new NoKeyGenerator();
-        } else if (tableInfo.getIdType() == IdType.AUTO) {
-            keyColumn = tableInfo.getKeyColumn();
-            keyProperty = tableInfo.getKeyProperty();
-            keyGenerator = new Jdbc3KeyGenerator();
-        } else if (tableInfo.getKeySequence() != null) {
-            keyColumn = tableInfo.getKeyColumn();
-            keyProperty = tableInfo.getKeyProperty();
-            String method = this.getMethod(SqlMethod.INSERT_ONE);
-            keyGenerator = TableInfoHelper.genKeyGenerator(method, tableInfo, this.builderAssistant);
-        } else {
-            keyGenerator = new NoKeyGenerator();
-        }
-        List<TableFieldInfo> fields = tableInfo.getFieldList();
-        String columns = tableInfo.getKeyInsertSqlColumn(false) +
-                this.filterTableFieldInfo(fields, null, TableFieldInfo::getInsertSqlColumn, EMPTY);
-        columns = columns.substring(0, columns.length() - 1);
-        String properties = tableInfo.getKeyInsertSqlProperty(null, false) +
-                this.filterTableFieldInfo(fields, null, i -> i.getInsertSqlProperty(null), EMPTY);
-        properties = properties.substring(0, properties.length() - 1);
-        String updates = this.filterTableFieldInfo(fields, null,
-                field -> field.getColumn() + " = values(" + field.getColumn() + ")", StringPool.COMMA);
-        String script = String.format(
+    protected String initializeMethodScript(@NonNull TableInfo table) {
+        List<TableFieldInfo> fields = table.getFieldList();
+        String columns = this.field2column(table, fields);
+        String properties = this.field2property(table, fields);
+        String updates = fields.stream().map(field -> {
+            CreateUpdate annotation = field.getField().getAnnotation(CreateUpdate.class);
+            if (annotation != null && !annotation.enabled()) {
+                return null;
+            }
+            StringBuilder buffer = new StringBuilder().append(field.getColumn()).append(" = ");
+            CreateUpdate.Mode mode = annotation == null ? CreateUpdate.Mode.REPLACE : annotation.mode();
+            if (mode == CreateUpdate.Mode.REPLACE) {
+                buffer.append("VALUES(").append(field.getColumn()).append(")");
+            } else if (mode == CreateUpdate.Mode.INCREMENT) {
+                buffer.append(field.getColumn()).append(" + 1");
+            } else if (mode == CreateUpdate.Mode.DECREMENT) {
+                buffer.append(field.getColumn()).append(" - 1");
+            } else {
+                throw new IllegalArgumentException("Not support update mode: " + mode);
+            }
+            return buffer.toString();
+        }).filter(StringUtils::notEmpty).collect(Collectors.joining(StringPool.COMMA));
+        return String.format(
                 "<script>\nINSERT IGNORE INTO %s (%s) VALUES (%s)\n ON DUPLICATE KEY UPDATE %s\n</script>",
-                tableInfo.getTableName(), columns, properties, updates
-        );
-        SqlSource source = this.languageDriver.createSqlSource(this.configuration, script, modelClass);
-        return this.addInsertMappedStatement(
-                mapperClass, modelClass, "insertUpdate", source, keyGenerator, keyProperty, keyColumn
+                table.getTableName(), columns, properties, updates
         );
     }
 }