我已经开始转换现有的Spring Boot(1.5.4.RELEASE)应用程序以支持多租户功能。所以我使用MySQL作为数据库,使用Spring Data JPA作为数据访问机制。我正在使用基于架构的多租户方法。正如Hibernate文件所建议的那样
https://docs.jboss.org/hibernate/orm/4.2/devguide/en-US/html/ch16.html
我已经实现了MultiTenantConnectionProvider
和CurrentTenantIdentifierResolver
接口,并且我正在使用ThreadLocal
变量来维护传入请求的当前租户。
public class TenantContext {
final public static String DEFAULT_TENANT = "master";
private static ThreadLocal<Tenant> tenantConfig = new ThreadLocal<Tenant>() {
@Override
protected Tenant initialValue() {
Tenant tenant = new Tenant();
tenant.setSchemaName(DEFAULT_TENANT);
return tenant;
}
};
public static Tenant getTenant() {
return tenantConfig.get();
}
public static void setTenant(Tenant tenant) {
tenantConfig.set(tenant);
}
public static String getTenantSchema() {
return tenantConfig.get().getSchemaName();
}
public static void clear() {
tenantConfig.remove();
}
}
然后我实现了一个过滤器,并在此处设置租户动态查看以下请求标头
String targetTenantName = request.getHeader(TENANT_HTTP_HEADER);
Tenant tenant = new Tenant();
tenant.setSchemaName(targetTenantName);
TenantContext.setTenant(tenant);
这很好,现在我的应用程序根据请求标头值指向不同的架构。
但是,存在一个主架构,我在其中存储一些全局设置,并且在请求租户时需要访问该架构。因此,我尝试在代码中的那个数据库调用之前对Threadlocal变量进行硬编码,如下所示。
Tenant tenant = new Tenant();
tenant.setSchemaName("master");
TenantContext.setTenant(tenant);
但是,这并不指向主模式,而是尝试在过滤器期间访问原始模式集。这是什么原因呢? 根据我的理解,Hibernate在对租户的第一个数据库调用期间会调用openSession(),而在我尝试为“ master”调用另一个数据库调用之后,它仍然使用先前的租户,因为CurrentTenantIdentifierResolver仅在openSession()期间调用。但是,这些不同的数据库调用不会在事务内调用。 您能否通过我的方法和解决此问题的任何建议来帮助我了解问题
谢谢 凯斯
@JonathanJohx实际上,我试图覆盖由其中一个控制器中的过滤器设置的TenantContext。首先,我登录一个TenantContext设置为该特定租户的租户。当请求在那个租户中时,我正在向主请求数据。为此,我只是对租户进行如下硬编码
@RestController
@RequestMapping("/jobTemplates")
public class JobTemplateController {
@Autowired
JobTemplateService jobTemplateService;
@GetMapping
public JobTemplateList list(Pageable pageable){
Tenant tenant = new Tenant();
tenant.setSchemaName(multitenantMasterDb);
TenantContext.setTenant(tenant);
return jobTemplateService.list(pageable);
}