gpt4 book ai didi

Spring Boot + Hibernate Multi-Tenancy : @Transactional not working

转载 作者:行者123 更新时间:2023-12-04 18:25:22 26 4
gpt4 key购买 nike

我有一个连接到单个 PostgreSQL 数据库的 Spring Boot 2 + Hibernate 5 Multi-Tenancy 应用程序。我已经根据这些指南进行了设置:

  • http://www.greggbolinger.com/tenant-per-schema-with-spring-boot/
  • https://blog.aliprax.me/schema-based-multitenancy/
  • https://fizzylogic.nl/2016/01/24/make-your-spring-boot-application-multi-tenant-aware-in-2-steps/

  • 只要我在到达 Controller 端点之前在过滤器或拦截器中设置了tenantId,这就可以正常工作。

    但是,我需要在 Controller 内设置租户 , 如下:
    @RestController
    public class CarController {
    @GetMapping("/cars")
    @Transactional
    public List<Car> getCars(@RequestParam(name = "schema") String schema) {
    TenantContext.setCurrentTenant(schema);
    return carRepo.findAll();
    }
    }

    但是此时已经检索到一个连接(对于公共(public)模式)并设置 TenantContext没有效果。

    我想 @Transactional应该强制方法在单独的事务中运行,因此 Hibernate session 的创建将推迟到 carRepo.findAll()方法被调用。情况似乎并非如此,因为 @Transactional什么也没做。

    这引出了两个问题:
  • 如何在请求期间推迟 Hibernate session 的创建,直到我设法根据过滤器/拦截器中不可用的某些逻辑设置正确的租户? @Transactional似乎什么也没做。
  • 如何在同一个请求或代码块中与不同的模式对话?想象一下 1 个存储库仅在公共(public)模式中可用,而 1 个在租户模式中。


  • 其他相关类(仅显示相关部分!)

    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);
    }
    }

    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;
    }
    }

    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;
    }
    }

    最佳答案

    虽然@tan-mally 用 @Transaction 解释了我的问题清楚以及如何解决它,实际问题是由不同的Spring Boot配置默认引起的:spring.jpa.open-in-view=true
    将此设置为 false 时, 我不需要 @Transaction注释。连接的检索将被推迟,直到它到达 repo 的 findAll()方法,在调用 TenantContext.setCurrentTenant(schema) 之后.

    显然 spring.jpa.open-in-view=true总是热切地围绕整个请求创建一个 Hibernate session 。

    希望这有助于下一个人遇到这个问题。我只是通过在启动期间弹出有关此默认设置的警告来提示此属性。见 this Github issue关于这个话题的讨论。

    关于Spring Boot + Hibernate Multi-Tenancy : @Transactional not working,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55973220/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com