需求背景:
在插入数据时需要提前设置 ID 和创建时间, 在更新时设置修改时间.
实现:
定义 Mybatis 拦截器只需要实现 Interceptor 类, 并通过注解设置需要拦截的对象即可:
type=>mybatis 的四大对象:[ParameterHandler],[ResultSetHandler],[StatementHandler],[Executor].
method => 四大对象中需要拦截的方法, 具体可以直接看源码. 例如 Executor 类的 update 方法就经常用到.
args=> 拦截方法所需要的参数, 如果不清楚的话也可以直接看源码. 例如 update 方法需要 MappedStatement 类型和 Object 类型的两个参数.
intercept(Invocation invocation)=> 此方法内写具体的拦截逻辑.
plugin()=> 没什么特殊要求的话直接写成如下形式即可, 意思是把定义的插件注册进插件链里面 (越晚注册越先执行).
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
setProperties(Properties properties)=> 对属性进行配置.
详细代码如下:
import com.eric.site.core.utils.SnowflakeIdWorker;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import java.lang.reflect.Field;
import java.util.Date;
import java.util.Properties;
/**
* @author Eric
*/
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
public class PrepareInterceptor implements Interceptor {
private Logger log = LoggerFactory.getLogger(PrepareInterceptor.class);
@Autowired
private SnowflakeIdWorker snowflakeIdWorker;
@Override
public Object intercept(Invocation invocation) throws Throwable {
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
//注解中method的值
String methodName = invocation.getMethod().getName();
//sql类型
SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
if ("update".equals(methodName)) {
Object object = invocation.getArgs()[1];
Date currentDate = new Date(System.currentTimeMillis());
//对有要求的字段填值
if (SqlCommandType.INSERT.equals(sqlCommandType)) {
Field fieldId = object.getClass().getDeclaredField("id");
fieldId.setAccessible(true);
long id = snowflakeIdWorker.nextId();
fieldId.set(object, id);
log.info("插入操作前设置id:{}", id);
Field fieldCreateTime = object.getClass().getDeclaredField("createTime");
fieldCreateTime.setAccessible(true);
fieldCreateTime.set(object, currentDate);
log.info("插入操作时设置create_time:{}", currentDate);
} else if (SqlCommandType.UPDATE.equals(sqlCommandType)) {
Field fieldModifyTime = object.getClass().getDeclaredField("modifyTime");
fieldModifyTime.setAccessible(true);
fieldModifyTime.set(object, currentDate);
log.info("更新操作时设置modify_time:{}", currentDate);
}
}
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}
配置
如果是配置文件的话, 在文件中的标签中追加如下内容:
<plugins>
<plugin interceptor="自定义插件类"></plugin>
</plugins>
如果是 springboot 的话则如下配置:
import com.eric.site.config.druid.DruidConfiguration;
import com.eric.site.config.mybatis.interceptors.PrepareInterceptor;
import com.github.pagehelper.PageHelper;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Properties;
/**
* mybatis的配置:<br/>
* <p>在配置plugin时,定义的越靠后则越先执行.<p/>
*
* @Author: Eric
*/
@Configuration
@MapperScan("com.eric.site.web.dao")
@AutoConfigureAfter(DruidConfiguration.class)
public class MybatisConfiguration {
/**
* 分页插件
*/
@Bean
public PageHelper pageHelper() {
PageHelper pageHelper = new PageHelper();
Properties p = new Properties();
p.setProperty("offsetAsPageNum", "true");
p.setProperty("rowBoundsWithCount", "true");
p.setProperty("reasonable", "true");
pageHelper.setProperties(p);
return pageHelper;
}
/**
* 前置拦截器,主要功能是插入前设置ID和create_time,更新时设置modify_time
*/
@Bean
public PrepareInterceptor idInterceptor() {
return new PrepareInterceptor();
}
}
这样就简单的实现了自定义拦截器.