模式区别
大约 3 分钟
DATASOURCE模式
DATASOURCE模式:又名 数据源模式、数据库模式。
是指每个租户对应一个数据库,应用启动时,会将所有租户的数据源加载到程序内存Map中,执行数据库操作时,动态切换数据源到当前租户的数据后并执行SQL。

DATASOURCE_COLUMN模式
DATASOURCE_COLUMN模式:又名 数据源&字段模式、数据源&列模式、大租户小门店模式、大租户小租户模式。
是指先用DATASOURCE模式隔离大租户,在用COLUMN模式隔离小租户。执行sql时,先利用DATASOURCE模式切换数据源,然后在使用COLUMN模式拦截器在对应的数据源中执行SQL动态改写,拼接上小租户的条件。
如原始SQL: select * from base_employee
- 先通过DATASOURCE模式动态切换数据源到 lamp_base_{TenantId} 数据库
- 在通过COLUMN模式 动态拼接SQL为: select * from base_employee where create_org_id = ${currentCompanyId}
- 最终效果: 在 lamp_base_{TenantId} 数据库执行: select * from base_employee where create_org_id = ${currentCompanyId}
切换模式
lamp-datasource-max 是同时支持上述2种模式的,在启动项目时,可以通过修改mysql.yml中的lamp.database.multiTenantType
参数修改。具体步骤:
微服务模式,需要修改nacos中配置文件: mysql.yml
lamp: database: multiTenantType: DATASOURCE_COLUMN # 可选项: DATASOURCE_COLUMN 和 DATASOURCE
单体模式,需要修改 application.yml
lamp:
database:
multiTenantType: DATASOURCE_COLUMN # 可选项: DATASOURCE_COLUMN 和 DATASOURCE
修改前端配置文件: .env
# 多租户类型 可选项: DATASOURCE_COLUMN 和 DATASOURCE VITE_GLOB_MULTI_TENANT_TYPE=DATASOURCE_COLUMN
示例代码
- 在需要根据大租户动态切换数据源的 ServiceImpl类 加上
@DS
注解
@Service
@DS("#thread.lamp_base")
public class EmployeeServiceImpl implements EmployeeService{
public Employee getById(Long id) {
// 动态切换到 ContextUtil.getBasePoolNameHeader() 库
dao.getById(id);
}
@Transactional(rollbackFor = Exception.class)
public void save(Employee employee) {
// 动态切换到 ContextUtil.getBasePoolNameHeader() 库
dao.insert(employee);
}
}
- 在需要根据小租户动态拼接SQL的 Mapper 类 加上
@TenantLine
注解。 若你启动的只是DATASOURCE模式,@TenantLine无任何效果。
/**
若原始sql为:
insert into employee(id, name) values (?, ?);
select * from employee;
加了 @TenantLine 后,sql 会自动替换为:
insert into employee(id, name, databaseProperties.getTenantIdColumn()) values (?, ?, ${ContextUtil.getCurrentCompanyId()});
select * from employee where {databaseProperties.getTenantIdColumn()} = ${ContextUtil.getCurrentCompanyId()};
databaseProperties.getTenantIdColumn() 和 ContextUtil.getCurrentCompanyId() 的取值,请详细阅读下方原理解析。
*/
@Repository
@TenantLine
public interface BaseEmployeeMapper extends SuperMapper<BaseEmployee> {
int insert(Employee employee);
Employee getById(Long id);
}
原理解析
配置为 DATASOURCE_COLUMN 模式后,项目启动时,会加载 LampTenantLineInnerInterceptor 拦截器
public class MybatisAutoConfiguration extends BaseMybatisConfiguration {
public MybatisAutoConfiguration(DatabaseProperties databaseProperties) {
super(databaseProperties);
}
@Override
protected List<InnerInterceptor> getPaginationBeforeInnerInterceptor() {
List<InnerInterceptor> list = new ArrayList<>();
// DATASOURCE_COLUMN 模式才会启用这个拦截器, DATASOURCE不会启用,所以 DATASOURCE模式下@TenantLine注解不会生效,也不必删除这行代码
if (MultiTenantType.DATASOURCE_COLUMN.eq(databaseProperties.getMultiTenantType())) {
log.info("检查到配置了:{}模式,已加载 column 部分插件", databaseProperties.getMultiTenantType());
// COLUMN 模式 多租户插件
LampTenantLineInnerInterceptor tli = new LampTenantLineInnerInterceptor();
tli.setTenantLineHandler(new TenantLineHandler() {
@Override
public String getTenantIdColumn() {
return databaseProperties.getTenantIdColumn();
}
@Override
public boolean ignoreTable(String tableName) {
return false;
}
@Override
public Expression getTenantId() {
return new LongValue(ContextUtil.getCurrentCompanyId());
}
});
list.add(tli);
}
}
}
拦截器区别
- COLUMN模式使用 TenantLineInnerInterceptor 拦截器来实现租户条件动态拼接,DATASOURCE_COLUMN模式使用LampTenantLineInnerInterceptor来实现。
- TenantLineInnerInterceptor 是 mybatis-plus 提供的拦截器,LampTenantLineInnerInterceptor是 灯灯 基于前者改造的。
- TenantLineInnerInterceptor 会将默认将所有的Mapper查询都动态拼接上条件
- LampTenantLineInnerInterceptor 则默认不会拼接
- TenantLineInnerInterceptor 可以通过在Mapper类上加
@InterceptorIgnore(tenantLine = "true")
,防止拦截器拼接条件 - LampTenantLineInnerInterceptor 则需要在Mapper类上加
@TenantLine
才会动态拼接条件 - 无其他区别,拼接SQL的逻辑和方法完全一致
👆🏻👆🏻👆🏻上面是评论区,对系统、本页文档什么疑问,可以在评论区留言。
❗️❗️❗️若评论区无法显示,请使用"手机热点"或"科学上网"。
❗️❗️❗️若评论区无法显示,请使用"手机热点"或"科学上网"。