赞
踩
Mybatis-plus多租户插件是一种用于实现多租户功能的插件,它基于Mybatis框架,通过拦截器机制实现对多租户的支持。该插件的核心组件包括TenantHandler和TenantInterceptor,其中TenantHandler用于处理租户相关的逻辑,如获取租户ID、设置租户信息等;而TenantInterceptor则用于拦截需要处理多租户的SQL语句,并在SQL中添加租户条件。
官方说明:
Mybatis-plus多租户插件的实现原理主要基于Mybatis的拦截器(Interceptor)机制,通过拦截器在需要执行的sql后面自动添加租户的查询条件,实现多租户功能。具体来说,Mybatis-plus提供了TenantLineInnerInterceptor租户处理器来实现多租户功能。在启用多租户后,所有执行的method的sql都会被处理,即自写的sql需要按照规范书写(sql涉及到多个表的每个表都要给别名,特别是inner join的要写标准的inner join)。
简单来说,Mybatis-plus多租户插件通过自定义Mybatis拦截器,在执行sql时自动添加租户的查询条件,实现多租户功能。
和基于物理隔离(分表)实现多租户不同,基于逻辑隔离(租户标识列,tenant_id)实现多租户是在每一张表中添加一个租户标识列(tenant_id),通过该列来区分各个租户的数据。
TenantLineInnerInterceptor插件也是基于逻辑隔离(租户标识列,tenant_id)实现多租户的,只不过它给我们封装了部分逻辑,让我们不用再SQL中显示地指定tenant_id作为条件,它会自动为我们拼接。
1、自定义TenantLineHandler
下面是TenantLineHandler 接口的定义,主要是用于获取租户ID和表是否需要需要租户隔离判断
/** * 租户处理器( TenantId 行级 ) * * @author hubin * @since 3.4.0 */ public interface TenantLineHandler { /** * 获取租户 ID 值表达式,只支持单个 ID 值 * <p> * * @return 租户 ID 值表达式 */ Expression getTenantId(); /** * 获取租户字段名 * <p> * 默认字段名叫: tenant_id * * @return 租户字段名 */ default String getTenantIdColumn() { return "tenant_id"; } /** * 根据表名判断是否忽略拼接多租户条件 * <p> * 默认都要进行解析并拼接多租户条件 * * @param tableName 表名 * @return 是否忽略, true:表示忽略,false:需要解析并拼接多租户条件 */ default boolean ignoreTable(String tableName) { return false; } /** * 忽略插入租户字段逻辑 * * @param columns 插入字段 * @param tenantIdColumn 租户 ID 字段 * @return */ default boolean ignoreInsert(List<Column> columns, String tenantIdColumn) { return columns.stream().map(Column::getColumnName).anyMatch(i -> i.equalsIgnoreCase(tenantIdColumn)); } }
自定义的TenantLineHandler ,我们需要按照自己的实际情况来定义自己的租户字段和获取
@Slf4j @Component public class MyTenantLineHandler implements TenantLineHandler { /** * 租户字段名 */ private static final String SYSTEM_TENANT_ID = "tenant_id"; /** * 默认的租户ID */ public static final Long DEFAULT_TENANT_ID = 1L; /** * 需要过滤的表 */ private static final List<String> IGNORE_TENANT_TABLES = new ArrayList<>(); /** * 获取租户ID值 * @return */ @Override public Expression getTenantId() { //获取登录用户的租户ID Long loginUserTenantId = getLoginUserTenantId(); if (loginUserTenantId == null){ loginUserTenantId = DEFAULT_TENANT_ID; } return new LongValue(loginUserTenantId); } /** * 租户字段名,默认是tenant_id,如果想改成其他字段,在这里返回即可 * @return */ @Override public String getTenantIdColumn() { return SYSTEM_TENANT_ID; } /** * 有不需要进行租户隔离的表,在这里返回true * @param tableName * @return */ @Override public boolean ignoreTable(String tableName) { return IGNORE_TENANT_TABLES.contains(tableName); } public Long getLoginUserTenantId(){ //模拟获取登录用户的租户ID,实际项目可以从登录用户缓存信息中获取 return 1L; } }
2、添加租户ID字段
我们的表和实体类都需要添加上租户ID字段
表字段
`tenant_id` bigint(20) NOT NULL COMMENT '多租户下的租户ID',
实体字段
@TableField("tenant_id")
private Long tenantId;
3、注册mybatisplus的多租户实现到 MybatisPlusInterceptor
@Configuration public class MybatisPlusConfig { /** * 添加MP插件 */ @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 添加多租户插件 interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new MyTenantLineHandler())); //如果配置多个插件,切记分页最后添加,如果有多数据源可以不配具体类型 否则都建议配上具体的DbType PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL); //设置单页分页最大数量 paginationInnerInterceptor.setMaxLimit(500L); interceptor.addInnerInterceptor(paginationInnerInterceptor); return interceptor; } }
完成上面配置之后,Mybatisplus就会帮我们在增删改查的所有操作都给拼接上携带租户条件。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。