Browse Source

Support JtaTransactionManager/SpringBeanContainer on HibernateJpaVendorAdapter

Makes ConfigurableJtaPlatform public and removes outdated WebSphere UOW check.

Closes gh-36216
pull/36221/head
Juergen Hoeller 1 week ago
parent
commit
c8c99d0464
  1. 6
      spring-orm/src/main/java/org/springframework/orm/jpa/hibernate/ConfigurableJtaPlatform.java
  2. 25
      spring-orm/src/main/java/org/springframework/orm/jpa/hibernate/LocalSessionFactoryBuilder.java
  3. 62
      spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.java

6
spring-orm/src/main/java/org/springframework/orm/jpa/hibernate/ConfigurableJtaPlatform.java

@ -31,14 +31,14 @@ import org.springframework.transaction.jta.UserTransactionAdapter; @@ -31,14 +31,14 @@ import org.springframework.transaction.jta.UserTransactionAdapter;
import org.springframework.util.Assert;
/**
* Implementation of Hibernate 5's JtaPlatform SPI, exposing passed-in {@link TransactionManager},
* Implementation of Hibernate's JtaPlatform SPI, exposing passed-in {@link TransactionManager},
* {@link UserTransaction} and {@link TransactionSynchronizationRegistry} references.
*
* @author Juergen Hoeller
* @since 7.0
* @since 7.0.4
*/
@SuppressWarnings("serial")
class ConfigurableJtaPlatform implements JtaPlatform {
public class ConfigurableJtaPlatform implements JtaPlatform {
private final TransactionManager transactionManager;

25
spring-orm/src/main/java/org/springframework/orm/jpa/hibernate/LocalSessionFactoryBuilder.java

@ -180,32 +180,25 @@ public class LocalSessionFactoryBuilder extends Configuration { @@ -180,32 +180,25 @@ public class LocalSessionFactoryBuilder extends Configuration {
/**
* Set the Spring {@link JtaTransactionManager} or the JTA {@link TransactionManager}
* to be used with Hibernate, if any. Allows for using a Spring-managed transaction
* manager for Hibernate 5's session and cache synchronization, with the
* manager for Hibernate's session and cache synchronization, with the
* "hibernate.transaction.jta.platform" automatically set to it.
* <p>A passed-in Spring {@link JtaTransactionManager} needs to contain a JTA
* {@link TransactionManager} reference to be usable here, except for the WebSphere
* case where we'll automatically set {@code WebSphereExtendedJtaPlatform} accordingly.
* {@link TransactionManager} reference to be usable here.
* <p>Note: If this is set, the Hibernate settings should not contain a JTA platform
* setting to avoid meaningless double configuration.
* @see AvailableSettings#JTA_PLATFORM
*/
public LocalSessionFactoryBuilder setJtaTransactionManager(Object jtaTransactionManager) {
Assert.notNull(jtaTransactionManager, "Transaction manager reference must not be null");
if (jtaTransactionManager instanceof JtaTransactionManager springJtaTm) {
boolean webspherePresent = ClassUtils.isPresent("com.ibm.wsspi.uow.UOWManager", getClass().getClassLoader());
if (webspherePresent) {
getProperties().put(AvailableSettings.JTA_PLATFORM,
"org.hibernate.engine.transaction.jta.platform.internal.WebSphereExtendedJtaPlatform");
}
else {
if (springJtaTm.getTransactionManager() == null) {
throw new IllegalArgumentException(
"Can only apply JtaTransactionManager which has a TransactionManager reference set");
}
getProperties().put(AvailableSettings.JTA_PLATFORM,
new ConfigurableJtaPlatform(springJtaTm.getTransactionManager(), springJtaTm.getUserTransaction(),
springJtaTm.getTransactionSynchronizationRegistry()));
if (springJtaTm.getTransactionManager() == null) {
throw new IllegalArgumentException(
"Can only apply JtaTransactionManager which has a TransactionManager reference set");
}
getProperties().put(AvailableSettings.JTA_PLATFORM,
new ConfigurableJtaPlatform(springJtaTm.getTransactionManager(), springJtaTm.getUserTransaction(),
springJtaTm.getTransactionSynchronizationRegistry()));
}
else if (jtaTransactionManager instanceof TransactionManager jtaTm) {
getProperties().put(AvailableSettings.JTA_PLATFORM,

62
spring-orm/src/main/java/org/springframework/orm/jpa/vendor/HibernateJpaVendorAdapter.java vendored

@ -23,6 +23,7 @@ import jakarta.persistence.EntityManager; @@ -23,6 +23,7 @@ import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.spi.PersistenceProvider;
import jakarta.persistence.spi.PersistenceUnitInfo;
import jakarta.transaction.TransactionManager;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AvailableSettings;
@ -38,7 +39,13 @@ import org.hibernate.dialect.SybaseDialect; @@ -38,7 +39,13 @@ import org.hibernate.dialect.SybaseDialect;
import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.orm.jpa.hibernate.ConfigurableJtaPlatform;
import org.springframework.orm.jpa.hibernate.SpringBeanContainer;
import org.springframework.orm.jpa.persistenceunit.SmartPersistenceUnitInfo;
import org.springframework.transaction.jta.JtaTransactionManager;
/**
* {@link org.springframework.orm.jpa.JpaVendorAdapter} implementation for Hibernate.
@ -65,7 +72,7 @@ import org.springframework.orm.jpa.persistenceunit.SmartPersistenceUnitInfo; @@ -65,7 +72,7 @@ import org.springframework.orm.jpa.persistenceunit.SmartPersistenceUnitInfo;
* @since 2.0
* @see HibernateJpaDialect
*/
public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter {
public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter implements BeanFactoryAware {
private final HibernateJpaDialect jpaDialect = new HibernateJpaDialect();
@ -75,6 +82,10 @@ public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter { @@ -75,6 +82,10 @@ public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter {
private final Class<? extends EntityManager> entityManagerInterface;
private @Nullable Object jtaTransactionManager;
private @Nullable BeanFactory beanFactory;
public HibernateJpaVendorAdapter() {
this.persistenceProvider = new SpringHibernateJpaPersistenceProvider();
@ -110,6 +121,29 @@ public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter { @@ -110,6 +121,29 @@ public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter {
this.jpaDialect.setPrepareConnection(prepareConnection);
}
/**
* Set the Spring {@link org.springframework.transaction.jta.JtaTransactionManager}
* or the JTA {@link jakarta.transaction.TransactionManager} to be used with Hibernate,
* if any. Implicitly sets up {@code JtaPlatform}.
* @since 7.0.4
* @see AvailableSettings#JTA_PLATFORM
*/
public void setJtaTransactionManager(Object jtaTransactionManager) {
this.jtaTransactionManager = jtaTransactionManager;
}
/**
* Set the Spring {@link ConfigurableListableBeanFactory} to use for a default
* Hibernate setup with {@link SpringBeanContainer}. This enables autowiring of
* Hibernate attribute converters and entity listeners.
* @since 7.0.4
* @see AvailableSettings#BEAN_CONTAINER
*/
@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
@Override
public PersistenceProvider getPersistenceProvider() {
@ -163,7 +197,31 @@ public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter { @@ -163,7 +197,31 @@ public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter {
PhysicalConnectionHandlingMode.DELAYED_ACQUISITION_AND_HOLD);
}
// For SpringBeanContainer to be called on Hibernate 6.2
// Derive Hibernate JtaPlatform from Spring (Jta)TransactionManager setup.
if (this.jtaTransactionManager != null) {
if (this.jtaTransactionManager instanceof JtaTransactionManager springJtaTm) {
if (springJtaTm.getTransactionManager() == null) {
throw new IllegalArgumentException(
"Can only apply JtaTransactionManager which has a TransactionManager reference set");
}
jpaProperties.put(AvailableSettings.JTA_PLATFORM, new ConfigurableJtaPlatform(
springJtaTm.getTransactionManager(), springJtaTm.getUserTransaction(),
springJtaTm.getTransactionSynchronizationRegistry()));
}
else if (this.jtaTransactionManager instanceof TransactionManager jtaTm) {
jpaProperties.put(AvailableSettings.JTA_PLATFORM, new ConfigurableJtaPlatform(jtaTm, null, null));
}
else {
throw new IllegalArgumentException(
"Unknown transaction manager type: " + this.jtaTransactionManager.getClass().getName());
}
}
// This enables autowiring of Hibernate attribute converters and entity listeners.
if (this.beanFactory instanceof ConfigurableListableBeanFactory clbf) {
jpaProperties.put(AvailableSettings.BEAN_CONTAINER, new SpringBeanContainer(clbf));
}
// For SpringBeanContainer to actually be called at runtime.
jpaProperties.put("hibernate.cdi.extensions", "true");
return jpaProperties;

Loading…
Cancel
Save