一、使用 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
}