我正在将一个Sping Boot 项目从2.7升级到3.1.5,其中包括将Hibernate 5升级到6.2。这完全破坏了我基于模式的多租户设置。我正在使用Postgres 12沿着Spring Data JPA,以及各种实体类和JpaRepository接口。我使用Testcontainers进行测试。
我的基于模式的多租户设置使用了MultiTenantConnectionProvider
和CurrentTenantIdentifierResolver
的实现,它们是@Component
Bean。升级后,如果我没有使用Hibernate属性注册连接提供程序(当隔离运行时),我只能通过涉及存储库和Testcontainers的测试;然而,这使得项目无法构建(使用Maven)。
在Sping Boot 2.7中,我必须让我的两个多租户组件都实现HibernatePropertiesCustomizer
,并通过AvailableSettings.MULTI_TENANT_ ...
向Hibernate属性注册它们自己(我知道MULTI_TENANT
类型属性本身在Hibernate 6中被删除了)。这是我能够让应用识别多租户组件的唯一方法。在Sping Boot 3.1.5和Hibernate 6.2中,TenantIdentifierResolver
注册自己很好-它只是导致测试失败的连接提供程序。但是如果我不注册它,我的应用程序根本无法构建,并且我没有多租户设置。
注册连接提供程序时出错:
org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:466)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.startTransaction(AbstractPlatformTransactionManager.java:400)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:601)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:385)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:164)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:244)
at jdk.proxy2/jdk.proxy2.$Proxy228.save(Unknown Source)
at org.fake.pckge.name.TestContainerTests.saveEntityToRepository(TestContainerTests.java:36)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
Caused by: org.hibernate.TransactionException: JDBC begin transaction failed:
at org.hibernate.resource.jdbc.internal.AbstractLogicalConnectionImplementor.begin(AbstractLogicalConnectionImplementor.java:78)
at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.begin(LogicalConnectionManagedImpl.java:282)
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.begin(JdbcResourceLocalTransactionCoordinatorImpl.java:232)
at org.hibernate.engine.transaction.internal.TransactionImpl.begin(TransactionImpl.java:83)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.beginTransaction(HibernateJpaDialect.java:164)
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:420)
... 85 more
Caused by: java.sql.SQLException: Connection is closed
字符串
我尝试过用其他方式注册连接提供程序,比如在HibernateConfig
Bean中,或者像this post建议的那样在MultiTenancyJpaConfiguration
中,以及在应用程序属性中。无论我在哪里注册它,我都会遇到同样的问题。我想知道这是不是一个鸡和蛋的问题,其中Bean的示例化太慢,无法与正确的模式建立连接。另一个难题是,我的TenantBasedConnectionProvider
依赖于一个自定义的@Configuration
Bean,该Bean加载应用程序YAML中的一些属性,例如要使用的schemata的名称。然而,就像我说的,这在Sping Boot 2.7中工作得很好,并且应该是可能的,因为Hibernate属性也在应用程序YAML中设置。
我该怎么办?
1条答案
按热度按时间yiytaume1#
我已经解决了它。这是一个红色的鲱鱼。在调试时,我在我的
PostgresIntegrationTest
接口中引入了@Container
注解,所有Testcontainer测试都实现了这个注解。这个注解在第一次测试运行后关闭Testcontainer。你不能使用@Container
或@ServiceConnection
-你必须使用@DynamicPropertyRegistry
并在方法中调用container.start()
另一个问题是,在
MultiTenantConnectionProvider.getConnection
中,我把连接放在try块的括号中,这意味着连接会自动关闭,你必须让它保持打开状态,让Hibernate来管理它。