我的问题很容易理解,但很难实现。
我有一个具有经典模式的 Spring Boot 应用程序(Controller / Service / Dao&Repository / Entity) 数据库中使用不同的模式。例如,我可以拥有 COMMON_SCHEMA.USERS 和 SPECIFIC_SCHEMA_A.ITEMS。
我认为最好的方法是实现多租户,这就是我所做的。
这是我的问题:
以下是使用的主要类。
public class MultitenantDataSource extends AbstractRoutingDataSource {
@Value("${defaultTenant}")
private String defaultTenant;
@Override
protected Object determineCurrentLookupKey() {
String currentTenant = TenantContext.getCurrentTenant();
return StringUtils.defaultIfBlank(currentTenant, defaultTenant);
}
}
public class TenantContext {
private static final ThreadLocal<String> currentTenant = new ThreadLocal<>();
public static void setCurrentTenant(String tenant) {
currentTenant.set(tenant);
}
public static String getCurrentTenant() {
return currentTenant.get();
}
public static void clear() {
currentTenant.remove();
}
}
@RestController
@RequiredArgsConstructor
public class TEST_ControllerImpl extends SessionFactoryUtil
implements TEST_Controller {
private final EvGroupService evGroupService;
@Override
public ResponseEntity<?> getGrp(String token, String grp) {
TenantContext.setCurrentTenant("COMMON_TENANT");
EvGroup result1 = evGroupService.findByCode(grp);
TenantContext.clear();
TenantContext.setCurrentTenant("SPECIFIC_TENANT_A");
EvGroup result2 = evGroupService.findByCode(grp);
TenantContext.clear();
return ResponseEntity.ok(convert(result1));
}
}
希望你的火花能够照亮我的一天/一周/一个月/一年:D 谢谢
我当然尝试过ChatGpt 我尝试在服务方法签名中设置@Transactionnal注释(即使使用Transactional.TxType.REQUIRES_NEW) 看了很多帖子,但都不是和我一样的问题。
尝试将以下属性设置为 false
spring:
jpa:
open-in-view: false
否则,一旦您打开数据库的会话 (
Connection
),它将保持打开状态,直到您退出控制器方法。因此,您无法真正在飞行中更改底层数据源。
您的代码中发生的情况如下:
@Override
public ResponseEntity<?> getGrp(String token, String grp) {
// sets tenant
TenantContext.setCurrentTenant("COMMON_TENANT");
// in background creates database connection using COMMON_TENANT key
EvGroup result1 = evGroupService.findByCode(grp);
// clears threadlocal
TenantContext.clear();
// sets tentant to SPECIFIC_TENANT_A
TenantContext.setCurrentTenant("SPECIFIC_TENANT_A");
// because spring.jpa.open-in-view is set to true connection is not closed
// but reused and still points to COMMON_TENANT
EvGroup result2 = evGroupService.findByCode(grp);
TenantContext.clear();
return ResponseEntity.ok(convert(result1));
}