基於Mybatis-Plus實現自動化操作創建時間和修改時間


引入

在實際開發中,總會避免不了操作數據庫,而在數據庫中每個表都會有create_timeupdate_time字段記錄操作時間,我們在操作這兩個時間的時候也可能會出現不一致的情況,或者說這兩個字段實際上應該是系統生成的,而不是用戶去手動處理,於是想着在新增和修改操作的時候能讓系統自動處理這兩個字段。

實戰

1.導入pom文件

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    &lt;dependency&gt;
        &lt;groupId&gt;mysql&lt;/groupId&gt;
        &lt;artifactId&gt;mysql-connector-java&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;com.baomidou&lt;/groupId&gt;
        &lt;artifactId&gt;mybatis-plus-boot-starter&lt;/artifactId&gt;
        &lt;version&gt;3.1.1&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;!--        &lt;dependency&gt;--&gt;
    &lt;!--            &lt;groupId&gt;org.mybatis.spring.boot&lt;/groupId&gt;--&gt;
    &lt;!--            &lt;artifactId&gt;mybatis-spring-boot-starter&lt;/artifactId&gt;--&gt;
    &lt;!--            &lt;version&gt;2.0.1&lt;/version&gt;--&gt;
    &lt;!--        &lt;/dependency&gt;--&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.projectlombok&lt;/groupId&gt;
        &lt;artifactId&gt;lombok&lt;/artifactId&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
        &lt;scope&gt;test&lt;/scope&gt;
    &lt;/dependency&gt;
&lt;/dependencies&gt;

注意
1.1.實現代碼中是基於Mybatis-plus實現;
1.2.如果不使用Mybatis-Plus可以使用注釋掉的依賴

2.實現SQL攔截器

@Intercepts(value = {@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
public class SqlInterceptor extends AbstractSqlParserHandler implements Interceptor {
/**
 * 創建時間
 */
private static final String CREATE_TIME = "createTime";
/**
 * 更新時間
 */
private static final String UPDATE_TIME = "updateTime";

@Override
public Object intercept(Invocation invocation) throws Throwable {
    MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
    // SQL操作命令
    SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
    // 獲取新增或修改的對象參數
    Object parameter = invocation.getArgs()[1];
    // 獲取對象中所有的私有成員變量(對應表字段)
    Field[] declaredFields = parameter.getClass().getDeclaredFields();
    if (parameter.getClass().getSuperclass() != null) {
        Field[] superField = parameter.getClass().getSuperclass().getDeclaredFields();
        declaredFields = ArrayUtils.addAll(declaredFields, superField);
    }
    // mybatis plus判斷
    boolean plus= parameter.getClass().getDeclaredFields().length == 1 &amp;&amp; parameter.getClass().getDeclaredFields()[0].getName().equals("serialVersionUID");

    //兼容mybatis plus
    if (plus) {
        Map&lt;String, Object&gt; updateParam = (Map&lt;String, Object&gt;) parameter;
        Class&lt;?&gt; updateParamType = updateParam.get("param1").getClass();
        declaredFields = updateParamType.getDeclaredFields();
        if (updateParamType.getSuperclass() != null) {
            Field[] superField = updateParamType.getSuperclass().getDeclaredFields();
            declaredFields = ArrayUtils.addAll(declaredFields, superField);
        }
    }
     String fieldName = null;
    for (Field field : declaredFields) {
       fieldName = field.getName();
        if (Objects.equals(CREATE_TIME, fieldName)) {
            if (SqlCommandType.INSERT.equals(sqlCommandType)) {
                field.setAccessible(true);
                field.set(parameter, new Timestamp(System.currentTimeMillis()));
            }
        }
        if (Objects.equals(UPDATE_TIME, fieldName)) {
            if (SqlCommandType.INSERT.equals(sqlCommandType) || SqlCommandType.UPDATE.equals(sqlCommandType)) {
                field.setAccessible(true);
                //兼容mybatis plus的update
                if (plus) {
                    Map&lt;String, Object&gt; updateParam = (Map&lt;String, Object&gt;) parameter;
                    field.set(updateParam.get("param1"), new Timestamp(System.currentTimeMillis()));
                } else {
                    field.set(parameter, new Timestamp(System.currentTimeMillis()));
                }
            }
        }
    }
    return invocation.proceed();
}

@Override
public Object plugin(Object target) {
    if (target instanceof Executor) {
        return Plugin.wrap(target, this);
    }
    return target;
}

@Override
public void setProperties(Properties properties) {
}

}

注意
2.1.這里寫死了CREATE_TIMEUPDATE_TIME 也是遵循約定大於配置的原則,而不需要再寫例如字段上增加上增加注解之類的方式實現,讓用戶使用更加簡潔。
2.2.這里繼承了Mybatis-Plus中AbstractSqlParserHandler 就可以不用自己重復造輪子去解析SQL,如果不是使用Mybatis-Plus則只需要直接實現Mybatis中的Interceptor 接口,自己實現SQL攔截解析即可。

3.注入自定義SQL攔截器

@Configuration
@MapperScan(value = "com.xx.mapper")
public class MybatisPlusConfig {
    @Bean
    public SqlInterceptor sqlInterceptor() {
        return new SqlInterceptor();
    }
}

   
   
  
  
          

注意
3.1.如果想要讓自定義的SQL攔截器生效,那么這一步必須有,即注入SqlInterceptor

4.工具類

public class ArrayUtils {
/**
 * 兩個數組相加
 * @param target
 * @param source
 * @return 相加后新的數組集合
 */
public static Field[] addAll(Field[] target, Field[] source) {
    if (target != null) {
        List&lt;Field&gt; fieldTarget = Stream.of(target).collect(Collectors.toList());
        if (source != null) {
            List&lt;Field&gt; fieldsSource = Stream.of(source).collect(Collectors.toList());
            for (Field field : fieldsSource) {
                fieldTarget.add(field);
            }
        }
        target = fieldTarget.toArray(new Field[fieldTarget.size()]);
        return target;
    }
    return target;
}

}

總結

1.導入pom文件,引入相關依賴;
2.繼承Mybatis-Plus中AbstractSqlParserHandler 抽象類,實現Mybatis的Interceptor接口,在對象轉換成SQL之前賦指定的字段值;
3.想要自定義的SQL攔截器生效,那么就需要注入自定義SQL攔截器。

原文地址:https://blog.csdn.net/caijwjava/article/details/90738471


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM