详解基于Mybatis-plus多租户实现方案
什么是多租户?
多租户(Multi-tenancy)指的是在同一套软件系统中,支持多个客户共享同一份代码,同时彼此之间又独立隔离,从而保证各个客户之间的数据互不干扰。
Mybatis-plus多租户实现方案
Mybatis-plus是Mybatis的增强工具包,其中提供了多租户的实现方案。
1. 引入依赖
首先需要引入Mybatis-plus的依赖,以及对应的驱动程序。具体依赖可以参考Mybatis-plus的官方文档。
2. 配置数据源
在Spring Boot中,我们可以通过application.properties或application.yml来配置数据源。
spring.datasource.url=jdbc:mysql://192.168.1.1:3306/mybatis_plus?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
3. 配置Mybatis-plus
在Spring Boot中,我们可以通过注解来自动配置Mybatis-plus。
@Configuration
@MapperScan("com.example.demo.mapper")
public class MybatisPlusConfig {
/**
* 多租户插件,默认开启
*/
@Bean
public TenantLineInnerInterceptor tenantLineInterceptor() {
return new TenantLineInnerInterceptor(new TenantLineHandler() {
/**
* 获取租户 ID 值表达式,只支持单个参数值(或无参数) <br>
* 例如:#{tenantId}、${tenantId}
*/
@Override
public Expression getTenantId() {
return new LongValue(1L);
}
/**
* 获取租户字段名,默认为:tenant_id
*/
@Override
public String getTenantIdColumn() {
return "tenant_id";
}
/**
* 过滤不需要拦截的表
*/
@Override
public boolean ignoreTable(String tableName) {
return "system".equalsIgnoreCase(tableName);
}
});
}
}
在上面的配置中,我们定义了租户字段名为tenant_id,租户ID为1,同时过滤了表名为system的表。
4. 配置Mybatis-plus插件
在Mybatis-plus中,我们可以使用插件来扩展Mybatis的功能。在这里,我们可以通过自定义插件来实现多租户的功能。
@Component
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
public class MultiTenantPlugin extends AbstractInterceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
final Object[] args = invocation.getArgs();
MappedStatement ms = (MappedStatement) args[0];
Object parameter = args[1];
if (ms.getSqlCommandType() == SqlCommandType.INSERT) {
if (parameter instanceof Map) {
Map map = (Map) parameter;
TenantContextHolder.getTenantId().ifPresent(tenantId -> map.put("tenant_id", tenantId));
} else if (parameter instanceof BaseEntity) {
BaseEntity entity = (BaseEntity) parameter;
TenantContextHolder.getTenantId().ifPresent(entity::setTenantId);
}
} else if (ms.getSqlCommandType() == SqlCommandType.SELECT) {
BoundSql boundSql = ms.getSqlSource().getBoundSql(parameter);
String sql = boundSql.getSql();
sql = "select * from (" + sql + ") a where a.tenant_id=" + TenantContextHolder.getTenantId().orElse(0L);
metaObject.setValue("delegate.boundSql.sql", sql);
}
return invocation.proceed();
}
}
上面的代码中,我们在插入数据的时候,自动将租户ID设置为当前用户的租户ID;在查询数据的时候,自动添加租户ID的过滤条件。
示例1:添加用户
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Override
public boolean addUser(User user) {
return save(user);
}
}
在上面的代码中,当我们调用addUser方法的时候,Mybatis-plus的多租户插件会自动将租户ID设置为当前用户的租户ID。
示例2:查询用户
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Override
public List<User> getUsers() {
return list();
}
}
在上面的代码中,当我们调用getUsers方法的时候,Mybatis-plus的多租户插件会自动添加租户ID的过滤条件。
总结
通过上面的介绍,我们可以看到,Mybatis-plus提供了非常方便的多租户实现方案,可以轻松解决多租户的难题。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解基于Mybatis-plus多租户实现方案 - Python技术站