基于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
posted @ 2019-12-12 16:06  星朝  阅读(8501)  评论(0编辑  收藏  举报