前言
QAQ没找到实习,只能照着官网自学,可我TM连多租户真正的场景都没遇到过
这个是自己学习时候记得笔记要是想详细了解可以去MP官网,上边有更详细的配置流程以及视频教学:MyBatis-Plus
概念
一种架构:实现在多用户环境下,共用相同的系统,同时确保各个用户之间的数据隔离性
实现方案
共有三种实现方案
- 独立数据库:一个租户一套数据库
优点:数据隔离级别高,为每个用户提供独立数据库,有助于数据模型拓展设计,满足各个用户自己的需求,出现故障时恢复数据简单
缺点:增大数据库安装数量,增大维护成本 - 共享数据库,独立Schema:多个或所有租户共享数据库,但每个租户有自己的Schema
优点:提供了安全程度较高的逻辑数据隔离,每个数据库支持更多租户数量
缺点:出现故障,数据恢复困难 - 共享数据库,共享Schema,共享数据表:在表中添加多租户的租户id。
共享程度最高,隔离级别最低;插入数据时数据多一个租户标识,数据备份、恢复困难
MyBatis-Plus对多租户的实现
多租户属于SQL解析部分,需要依赖分页插件
- MyBatisPlusConfig中配置分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
// 1. 分页插件
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
// 2. 多租户SQL解析器接口
ArrayList<ISqlParser> sqlParserList = new ArrayList<ISqlParser>();
// 3. 创建租户SQL解析器
TenantSqlParser tenantSqlParser = new TenantSqlParser();
// 4. 设置TenantHandler
tenantSqlParser.setTenantHandler(new TenantHandler() {
@Override
public Expression getTenantId(boolean select) {
// 租户实际传来的信息
return new LongValue(6);
}
@Override
public String getTenantIdColumn() {
// 获取区分多租户的 表中字段名
return "type_id";
}
@Override
public boolean doTableFilter(String tableName) {
// 指定字段或者表加租户信息,false为加 ; true为不加
if ("tbl_role".equals(tableName)) {
return true;
}
return false;
}
});
// 5. 将多租户解析器设置到list中
sqlParserList.add(tenantSqlParser);
// 6. 将list放到分页器中
paginationInterceptor.setSqlParserList(sqlParserList);
return paginationInterceptor;
}
- 执行查询(删改查都会根据配置,添加租户信息)
此处例子为一个查询所有的方法,除了判断deleted标为位为未删除,还要将租户匹配放到查询条件
特定SQL过滤
有些特定的增删改查方法,例如selectById(),不想增加租户信息为条件;而其他方法可以加入租户信息
- 通用方法:自定义过滤器,通过在分页插件中设置SQL过滤器
// 设置SQL过滤器
paginationInterceptor.setSqlParserFilter(new ISqlParserFilter() {
@Override
public boolean doFilter(MetaObject metaObject) {
MappedStatement ms = SqlParserHelper.getMappedStatement(metaObject);
// 使用权限定名
if ("com.example.demo.type.dao.TypeMapper.selectById".equals(ms.getId())){
return true; // 返回值为true,执行sql时不添加租户信息条件
}
return false; // 返回值为false,代表都增加租户信息作为条件
}
});
此时使用TypeMapper执行selectById()进行查询时,where中没有对租户的查询
- 自定义方法:在mapper中的自定义方法
public interface TypeMapper extends BaseMapper<Type> {
@SqlParser(filter = true) // 此设置会过滤租户信息
@Update("update tbl_type set name = #{name} where type_id = #{id}")
public void updateCustom(@Param("id") int id,@Param("name")String name);
}