跳至主要內容

数据源和大租户小门店模式区别

大约 3 分钟快速启动快速启动模式区别

DATASOURCE模式

DATASOURCE模式:又名 数据源模式、数据库模式。

是指每个租户对应一个数据库,应用启动时,会将所有租户的数据源加载到程序内存Map中,执行数据库操作时,动态切换数据源到当前租户的数据后并执行SQL。

DATASOURCE模式原理
DATASOURCE模式原理

DATASOURCE_COLUMN模式

DATASOURCE_COLUMN模式:又名 数据源&字段模式、数据源&列模式、大租户小门店模式、大租户小租户模式。

是指先用DATASOURCE模式隔离大租户,在用COLUMN模式隔离小租户。执行sql时,先利用DATASOURCE模式切换数据源,然后在使用COLUMN模式拦截器在对应的数据源中执行SQL动态改写,拼接上小租户的条件。

如原始SQL: select * from base_employee

  1. 先通过DATASOURCE模式动态切换数据源到 lamp_base_{TenantId} 数据库
  2. 在通过COLUMN模式 动态拼接SQL为: select * from base_employee where create_org_id = ${currentCompanyId}
  3. 最终效果: 在 lamp_base_{TenantId} 数据库执行: select * from base_employee where create_org_id = ${currentCompanyId}

切换模式

lamp-cloud-pro-datasource-column 和 lamp-boot-pro-datasource-column 项目是同时支持上述2种模式的,在启动项目时,可以通过修改mysql.yml中的lamp.database.multiTenantType 参数修改。具体步骤:

  1. 2种模式使用的源码都是 lamp-cloud-pro-datasource-column 或 lamp-boot-pro-datasource-column、lamp-web-pro

  2. lamp-cloud-pro-datasource-column 修改nacos中配置文件: mysql.yml

lamp:
  database:
    multiTenantType: DATASOURCE_COLUMN  # 可选项: DATASOURCE_COLUMN  和 DATASOURCE  
  1. lamp-boot-pro-datasource-column 修改 application.ymlopen in new window

lamp:
  database:
    multiTenantType: DATASOURCE_COLUMN  # 可选项: DATASOURCE_COLUMN  和 DATASOURCE 

  1. 修改前端配置文件: .env

    # 多租户类型     可选项: DATASOURCE_COLUMN  和 DATASOURCE 
    VITE_GLOB_MULTI_TENANT_TYPE=DATASOURCE_COLUMN    	
    

示例代码

  1. 在需要根据大租户动态切换数据源的 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);
    }
}
  1. 在需要根据小租户动态拼接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);
        }
    }
}

拦截器区别

  1. COLUMN模式使用 TenantLineInnerInterceptor 拦截器来实现租户条件动态拼接,DATASOURCE_COLUMN模式使用LampTenantLineInnerInterceptor来实现。
  2. TenantLineInnerInterceptor 是 mybatis-plus 提供的拦截器,LampTenantLineInnerInterceptor是 灯灯 基于前者改造的。
  3. TenantLineInnerInterceptor 会将默认将所有的Mapper查询都动态拼接上条件
  4. LampTenantLineInnerInterceptor 则默认不会拼接
  5. TenantLineInnerInterceptor 可以通过在Mapper类上加 @InterceptorIgnore(tenantLine = "true") ,防止拦截器拼接条件
  6. LampTenantLineInnerInterceptor 则需要在Mapper类上加 @TenantLine 才会动态拼接条件
  7. 无其他区别,拼接SQL的逻辑和方法完全一致
👆🏻👆🏻👆🏻上面是评论区,对系统、本页文档什么疑问,可以在评论区留言。
❗️❗️❗️若评论区无法显示,请使用"手机热点"或"科学上网"。