文章目录
说明
MyBatis Inteceptor
是使用JDK的动态代理来实现的,所以它只能对接口进行拦截
里面两个很重要的注解是:@Intercepts
、@Signature
-
@Intercepts
: 标记要拦截的方法签名 -
@Signature
: 方法签名,唯一的标记一个接口的方法
Mybatis
支持对 Executor
、 StatementHandler
、 ResultSetHandler
和 PameterHandler
进行拦截,也就是说会对这4种对象进行代理。
Executor
:作用是执行SQL语句(所有的sql),并且对事务、缓存等提供统一接口。(在这一层上做拦截的权限会更大)StatementHandler
: 作用是对 statement 进行预处理,并且提供统一的原子的增、删、改、查接口。(如果要在SQL执行前进行拦截的话,拦截这里就可以了)ResultSetHandler
: 作用是对返回结果ResultSet
进行处理。PameterHandler
: 作用是对参数进行赋值。
示例
@Intercepts(@Signature(method = "update", type = Executor.class, args = {MappedStatement.class, Object.class}))
public class MybatisSnowFlakeIdPlus implements Interceptor {
...
}
@Intercepts(@Signature(method = "setParameters", type = ParameterHandler.class, args = {PreparedStatement.class}))
public class PameterPlus implements Interceptor {
...
}
mybatis自定义Id赋值示例
import com.wss.busines.demo.utils.snowflake.IdWorker;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.persistence.Id;
import java.lang.reflect.Field;
import java.util.Properties;
/**
* MybatisSnowFlakeIdPlus
*
* @author XCX
*/
@Component
@Intercepts(@Signature(method = "update", type = Executor.class, args = {MappedStatement.class, Object.class}))
public class MybatisSnowFlakeIdPlus implements Interceptor {
@Autowired
private IdWorker idWorker;
@Override
public Object intercept(Invocation invocation) throws Throwable {
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
if (sqlCommandType != SqlCommandType.INSERT) {
return invocation.proceed();
}
Object paramObj = invocation.getArgs()[1];
BoundSql boundSql = mappedStatement.getBoundSql(paramObj);
if (paramObj == null) {
return invocation.proceed();
}
Class<?> clazz = paramObj.getClass();
Field[] thisFields = clazz.getDeclaredFields();
for (Field field : thisFields) {
field.setAccessible(true);
Object value = field.get(paramObj);
// 已赋值,直接跳过
if (null != value) {
continue;
}
if (null != field.getAnnotation(Id.class)) {
if (field.getType() == String.class) {
if (boundSql.hasAdditionalParameter("id_bind")) {
field.set(paramObj, boundSql.getAdditionalParameter("id_bind"));
} else {
String id = String.valueOf(idWorker.nextId());
field.set(paramObj, id);
}
} else {
System.out.println("Type is not Stirng");
}
}
}
return invocation.proceed();
}
@Override
public Object plugin(Object o) {
return Plugin.wrap(o, this);
}
@Override
public void setProperties(Properties properties) {
}
}