Chr*_*ker 4 spring hibernate jpa multi-tenant spring-boot
我有一个 Spring Boot 2 + Hibernate 5 多租户应用程序连接到单个 PostgreSQL 数据库。我已经根据这些指南进行了设置:
只要我在访问控制器端点之前在过滤器或拦截器中设置tenantId,就可以正常工作。
但是,我需要在控制器内设置租户,如下所示:
@RestController
public class CarController {
@GetMapping("/cars")
@Transactional
public List<Car> getCars(@RequestParam(name = "schema") String schema) {
TenantContext.setCurrentTenant(schema);
return carRepo.findAll();
}
}
Run Code Online (Sandbox Code Playgroud)
但此时已经检索到连接(对于公共模式)并且设置TenantContext没有任何效果。
我认为@Transactional应该强制该方法在单独的事务中运行,因此 Hibernate 会话的创建将被推迟到carRepo.findAll()调用该方法为止。情况似乎并非如此,因为@Transactional什么也没做。
这让我想到两个问题:
@Transactional似乎什么也没做。其他相关类(仅显示相关部分!)
MultiTenantConnectionProviderImpl.java:
@Component
public class MultiTenantConnectionProviderImpl implements MultiTenantConnectionProvider {
@Override
public Connection getConnection(String tenantIdentifier) throws SQLException {
final Connection connection = getAnyConnection();
connection.setSchema(tenantIdentifier);
return connection;
}
@Override
public void releaseConnection(String tenantIdentifier, Connection connection) throws SQLException {
connection.setSchema(null);
releaseAnyConnection(connection);
}
}
Run Code Online (Sandbox Code Playgroud)
TenantIdentifierResolver.java
@Component
public class TenantIdentifierResolver implements CurrentTenantIdentifierResolver {
@Override
public String resolveCurrentTenantIdentifier() {
String tenantId = TenantContext.getCurrentTenant();
return (tenantId != null) ? tenantId : "public";
}
@Override
public boolean validateExistingCurrentSessions() {
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
HibernateConfig.java:
@Configuration
public class HibernateConfig {
@Autowired
private JpaProperties jpaProperties;
@Bean
public JpaVendorAdapter jpaVendorAdapter() {
return new HibernateJpaVendorAdapter();
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource,
MultiTenantConnectionProvider multiTenantConnectionProviderImpl,
CurrentTenantIdentifierResolver currentTenantIdentifierResolverImpl) {
Map<String, Object> properties = new HashMap<>(jpaProperties.getProperties());
properties.put(Environment.MULTI_TENANT, MultiTenancyStrategy.SCHEMA);
properties.put(Environment.MULTI_TENANT_CONNECTION_PROVIDER, multiTenantConnectionProviderImpl);
properties.put(Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, currentTenantIdentifierResolverImpl);
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource);
em.setPackagesToScan("com.example");
em.setJpaVendorAdapter(jpaVendorAdapter());
em.setJpaPropertyMap(properties);
return em;
}
}
Run Code Online (Sandbox Code Playgroud)
虽然 @tan-mally@Transaction清楚地解释了我的问题以及如何解决它,但实际问题是由不同的 Spring Boot 配置默认值引起的:spring.jpa.open-in-view=true
当将此设置为 时,我根本false不需要注释。@TransactionConnection 的检索将被推迟findAll(),直到它在调用TenantContext.setCurrentTenant(schema).
显然spring.jpa.open-in-view=true,总是围绕整个请求急切地创建一个 Hibernate 会话。
希望这可以帮助下一个遇到这个问题的人。我只是通过启动期间弹出的有关此默认设置的警告暗示了此属性。请参阅此 Github 问题以获取有关此主题的讨论。
| 归档时间: |
|
| 查看次数: |
4006 次 |
| 最近记录: |