关于Mybatis扩展:自定义Id赋值示例

说明

MyBatis Inteceptor是使用JDK的动态代理来实现的,所以它只能对接口进行拦截

​ 里面两个很重要的注解是:@Intercepts@Signature

  • @Intercepts : 标记要拦截的方法签名

  • @Signature : 方法签名,唯一的标记一个接口的方法

Mybatis支持对 ExecutorStatementHandlerResultSetHandlerPameterHandler 进行拦截,也就是说会对这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) {
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

推到油瓶不扶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值