mybatis多租户 update拦截器 拦截tenantId的更新 也可应用到其它功能
核心思路
拦截Executor的update方法,修改sqlSource中记录的映射信息 mybatis的版本是3.2 sqlNode的结构根据自身使用版本修改
源码
/**
* update拦截器 执行update语句时忽略tenantId字段的插入 避免外部将null值传入
*/
//@Component
@Slf4j
@Intercepts(@Signature(type = Executor.class, method = "update", args = {
MappedStatement.class, Object.class}))
public class UpdateHandlerInterceptor implements Interceptor {
/*
当实体类存在@TableField(value = "tenant_id")注解的tenantId字段时,窜租户的风险,需给注解添加exist = false 应无法保证 现加拦截器处理逻辑
@ApiModelProperty(value = "租户id")
@TableField(value = "tenant_id")
private Long tenantId;
*/
// mybatis中sqlSource的处理应该是在读取xml初始化的过程中 无需重复替换sqlNode内容处理 todo 添加sqlSource的官方解释
private static final List<String> ignoredTableClassName = new ArrayList<>();
@Override
public Object intercept(Invocation invocation) throws Throwable {
// 获取上下文中的tenantId 为空时不处理
Long currentTenantId = CommonContext.getCurrentTenantId();
if (currentTenantId == null) {
return invocation.proceed();
}
// 获取参数
MappedStatement ms = (MappedStatement) invocation.getArgs()[0];
Object parameterObject = invocation.getArgs()[1];
// insert语句在 TenantSqlParser的processInsert中会通过租户上下文强制插入租户id
// 只处理update语句 根据我们自己业务封装的update方法(逻辑为getById拿到数据后进行非空字段拷贝==仅能排除空租户id的更新 替换还是没有办法) 以外的方法 都需要被拦截处理