java 升级到6.2后,Hibernate多租户失败

wh6knrhe  于 5个月前  发布在  Java
关注(0)|答案(1)|浏览(60)

我正在将一个Sping Boot 项目从2.7升级到3.1.5,其中包括将Hibernate 5升级到6.2。这完全破坏了我基于模式的多租户设置。我正在使用Postgres 12沿着Spring Data JPA,以及各种实体类和JpaRepository接口。我使用Testcontainers进行测试。
我的基于模式的多租户设置使用了MultiTenantConnectionProviderCurrentTenantIdentifierResolver的实现,它们是@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中设置。
我该怎么办?

yiytaume

yiytaume1#

我已经解决了它。这是一个红色的鲱鱼。在调试时,我在我的PostgresIntegrationTest接口中引入了@Container注解,所有Testcontainer测试都实现了这个注解。这个注解在第一次测试运行后关闭Testcontainer。你不能使用@Container@ServiceConnection-你必须使用@DynamicPropertyRegistry并在方法中调用container.start()
另一个问题是,在MultiTenantConnectionProvider.getConnection中,我把连接放在try块的括号中,这意味着连接会自动关闭,你必须让它保持打开状态,让Hibernate来管理它。

相关问题