Bootstrap

MybatisPlus实现多租户 全局拦截器

一、使用 MyBatis-Plus 内置的 TenantLineInnerInterceptor 实现多租户

对特定字段做全局过滤,并让这个条件应用于所有表的查询,可以使用 TenantLineHandler 来为所有表自动加上用户 ID 的过滤条件。

1.创建一个自定义的 TenantLineHandler 来指定要过滤的字段(租户ID)。

import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import org.springframework.stereotype.Component;

@Component
public class CustomTenantLineHandler implements TenantLineHandler {

    @Override
    public Expression getTenantId() {
        // 返回租户 ID,这里你可以从上下文中获取租户 ID,比如从用户的 session 或 token 中
        return new LongValue(12345); // 假设 ID 为 12345
    }

    @Override
    public boolean ignoreTable(String tableName) {
        // 指定不需要添加过滤条件的表
        // 返回true表示忽略此表
        return tableName.equalsIgnoreCase("demo");  // 如果所有表都需要过滤条件,返回 false
    }

    @Override
    public String getTenantIdColumn() {
        // 指定租户 ID 字段名称,比如 "station_id"
        return "tenant_id";
    }
}

2.在MyBatis-Plus配置类中注册 TenantLineInnerInterceptor,并注入自定义的 TenantLineHandler

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(CustomTenantLineHandler tenantLineHandler) {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 注册多租户 SQL 解析器
        interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(tenantLineHandler));
        return interceptor;
    }
}

这样,在所有查询操作中,tenant_id 字段都会自动被加入到 WHERE 条件中,无需在每次查询时手动添加。

二、使用 MetaObjectHandler 自动填充租户 ID

在 MyBatis-Plus 的多租户模式下,默认情况下TenantLineInnerInterceptor 插件只对 查询、更新和删除操作 添加租户 ID 过滤,而不会在 插入操作 中自动插入租户 ID 字段。MyBatis-Plus 提供了 MetaObjectHandler 接口,可以用来在插入或更新操作时自动填充某些字段。你可以通过这个功能实现插入时自动填充租户 ID。

1.定义一个 MetaObjectHandler 来在插入操作时自动填充租户 ID 字段。

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

@Component
public class CustomMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        // 根据实体类类型判断是否需要填充租户 ID
        Object entity = metaObject.getOriginalObject();
        // 根据实体类类型判断是否需要填充租户 ID
        if (entity instanceof Order) { // 假设只对 Order 表进行租户 ID 填充
            // 自动填充租户 ID
            this.strictInsertFill(metaObject, "tenantId", Long.class, TenantContextHolder.getTenantId());
        }
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        // 更新时自动填充租户ID或其他字段
    }

    // 模拟从上下文或线程本地中获取当前的租户ID
    private Long getCurrentStationId() {
        // 比如从 session 或线程本地获取当前的租户ID
        return 12345L; // 假设当前租户ID为12345
    }
}

2.在实体类中标注 @TableField

需要在实体类中通过 @TableField(fill = FieldFill.INSERT) 注解来指定哪些字段支持自动填充

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.FieldFill;

public class YourEntity {
    
    // 其他字段...

    @TableField(fill = FieldFill.INSERT)
    private Long tenantId;

    // Getter 和 Setter
}

;