Compatibility with Hibernate 4.3
Due to key SPI interfaces such as ConnectionProvider and JtaPlatform changing their package location in Hibernate 4.3, we have to resort to reflection in a few places. Most importantly, the ConfigurableJtaPlatform used by the setJtaTransactionManager method has now been redesigned as a reflective proxy. Issue: SPR-10839
This commit is contained in:
		
							parent
							
								
									0b37cec287
								
							
						
					
					
						commit
						a9e727cd88
					
				| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright 2002-2012 the original author or authors.
 | 
					 * Copyright 2002-2013 the original author or authors.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 * you may not use this file except in compliance with the License.
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
| 
						 | 
					@ -16,60 +16,137 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package org.springframework.orm.hibernate4;
 | 
					package org.springframework.orm.hibernate4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.lang.reflect.InvocationHandler;
 | 
				
			||||||
 | 
					import java.lang.reflect.Method;
 | 
				
			||||||
 | 
					import java.lang.reflect.Proxy;
 | 
				
			||||||
 | 
					import javax.transaction.Status;
 | 
				
			||||||
 | 
					import javax.transaction.Synchronization;
 | 
				
			||||||
 | 
					import javax.transaction.SystemException;
 | 
				
			||||||
 | 
					import javax.transaction.Transaction;
 | 
				
			||||||
import javax.transaction.TransactionManager;
 | 
					import javax.transaction.TransactionManager;
 | 
				
			||||||
 | 
					import javax.transaction.TransactionSynchronizationRegistry;
 | 
				
			||||||
import javax.transaction.UserTransaction;
 | 
					import javax.transaction.UserTransaction;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.hibernate.service.jta.platform.internal.AbstractJtaPlatform;
 | 
					import org.hibernate.TransactionException;
 | 
				
			||||||
 | 
					import org.hibernate.service.Service;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.springframework.transaction.jta.UserTransactionAdapter;
 | 
					import org.springframework.transaction.jta.UserTransactionAdapter;
 | 
				
			||||||
import org.springframework.util.Assert;
 | 
					import org.springframework.util.Assert;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Implementation of Hibernate 4's {@link org.hibernate.service.jta.platform.spi.JtaPlatform}
 | 
					 * Implementation of Hibernate 4's JtaPlatform SPI (which has a different package
 | 
				
			||||||
 * SPI, exposing passed-in {@link TransactionManager} and {@link UserTransaction} references.
 | 
					 * location in Hibernate 4.0-4.2 vs 4.3), exposing passed-in {@link TransactionManager},
 | 
				
			||||||
 | 
					 * {@link UserTransaction} and {@link TransactionSynchronizationRegistry} references.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @author Juergen Hoeller
 | 
					 * @author Juergen Hoeller
 | 
				
			||||||
 * @since 3.1.2
 | 
					 * @since 3.1.2
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@SuppressWarnings("serial")
 | 
					@SuppressWarnings({"serial", "unchecked"})
 | 
				
			||||||
class ConfigurableJtaPlatform extends AbstractJtaPlatform {
 | 
					class ConfigurableJtaPlatform implements InvocationHandler {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static final Class<? extends Service> jtaPlatformClass;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static {
 | 
				
			||||||
 | 
							Class<?> jpClass;
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								// Try Hibernate 4.0-4.2 JtaPlatform variant
 | 
				
			||||||
 | 
								jpClass = SpringSessionContext.class.getClassLoader().loadClass(
 | 
				
			||||||
 | 
										"org.hibernate.service.jta.platform.spi.JtaPlatform");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							catch (ClassNotFoundException ex) {
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
 | 
									// Try Hibernate 4.3 JtaPlatform variant
 | 
				
			||||||
 | 
									jpClass = SpringSessionContext.class.getClassLoader().loadClass(
 | 
				
			||||||
 | 
											"org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform");
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								catch (ClassNotFoundException ex2) {
 | 
				
			||||||
 | 
									throw new IllegalStateException("Neither Hibernate 4.0-4.2 nor 4.3 variant of JtaPlatform found");
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							jtaPlatformClass = (Class<? extends Service>) jpClass;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						static String getJtaPlatformBasePackage() {
 | 
				
			||||||
 | 
							String className = jtaPlatformClass.getName();
 | 
				
			||||||
 | 
							return className.substring(0, className.length() - "spi.JtaPlatform".length());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private final TransactionManager transactionManager;
 | 
						private final TransactionManager transactionManager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private final UserTransaction userTransaction;
 | 
						private final UserTransaction userTransaction;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private final TransactionSynchronizationRegistry transactionSynchronizationRegistry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Create a new ConfigurableJtaPlatform instance with the given
 | 
						 * Create a new ConfigurableJtaPlatform instance with the given
 | 
				
			||||||
	 * JTA TransactionManager and optionally a given UserTransaction.
 | 
						 * JTA TransactionManager and optionally a given UserTransaction.
 | 
				
			||||||
	 * @param tm the JTA TransactionManager reference (required)
 | 
						 * @param tm the JTA TransactionManager reference (required)
 | 
				
			||||||
	 * @param ut the JTA UserTransaction reference (optional)
 | 
						 * @param ut the JTA UserTransaction reference (optional)
 | 
				
			||||||
 | 
						 * @param tsr the JTA 1.1 TransactionSynchronizationRegistry (optional)
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public ConfigurableJtaPlatform(TransactionManager tm, UserTransaction ut) {
 | 
						public ConfigurableJtaPlatform(TransactionManager tm, UserTransaction ut, TransactionSynchronizationRegistry tsr) {
 | 
				
			||||||
		Assert.notNull(tm, "TransactionManager reference must not be null");
 | 
							Assert.notNull(tm, "TransactionManager reference must not be null");
 | 
				
			||||||
		this.transactionManager = tm;
 | 
							this.transactionManager = tm;
 | 
				
			||||||
		this.userTransaction = (ut != null ? ut : new UserTransactionAdapter(tm));
 | 
							this.userTransaction = (ut != null ? ut : new UserTransactionAdapter(tm));
 | 
				
			||||||
 | 
							this.transactionSynchronizationRegistry = tsr;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						public TransactionManager retrieveTransactionManager() {
 | 
				
			||||||
	protected TransactionManager locateTransactionManager() {
 | 
					 | 
				
			||||||
		return this.transactionManager;
 | 
							return this.transactionManager;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						public UserTransaction retrieveUserTransaction() {
 | 
				
			||||||
	protected UserTransaction locateUserTransaction() {
 | 
					 | 
				
			||||||
		return this.userTransaction;
 | 
							return this.userTransaction;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						public Object getTransactionIdentifier(Transaction transaction) {
 | 
				
			||||||
	protected boolean canCacheTransactionManager() {
 | 
							return transaction;
 | 
				
			||||||
		return true;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public boolean canRegisterSynchronization() {
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								return (this.transactionManager.getStatus() == Status.STATUS_ACTIVE);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							catch (SystemException ex) {
 | 
				
			||||||
 | 
								throw new TransactionException("Could not determine JTA transaction status", ex);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public void registerSynchronization(Synchronization synchronization) {
 | 
				
			||||||
 | 
							if (this.transactionSynchronizationRegistry != null) {
 | 
				
			||||||
 | 
								this.transactionSynchronizationRegistry.registerInterposedSynchronization(synchronization);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								try {
 | 
				
			||||||
 | 
									this.transactionManager.getTransaction().registerSynchronization(synchronization);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								catch (Exception ex) {
 | 
				
			||||||
 | 
									throw new TransactionException("Could not access JTA Transaction to register synchronization", ex);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public int getCurrentStatus() throws SystemException {
 | 
				
			||||||
 | 
							return this.transactionManager.getStatus();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
	protected boolean canCacheUserTransaction() {
 | 
						public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 | 
				
			||||||
		return true;
 | 
							Method targetMethod = getClass().getMethod(method.getName(), method.getParameterTypes());
 | 
				
			||||||
 | 
							return targetMethod.invoke(this, args);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Obtain a proxy that implements the current Hibernate version's JtaPlatform interface
 | 
				
			||||||
 | 
						 * in the right package location, delegating all invocations to the same-named methods
 | 
				
			||||||
 | 
						 * on this ConfigurableJtaPlatform class itself.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public Object getJtaPlatformProxy() {
 | 
				
			||||||
 | 
							return Proxy.newProxyInstance(getClass().getClassLoader(), new Class<?>[] {jtaPlatformClass}, this);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,7 +33,6 @@ import org.hibernate.cfg.AvailableSettings;
 | 
				
			||||||
import org.hibernate.cfg.Configuration;
 | 
					import org.hibernate.cfg.Configuration;
 | 
				
			||||||
import org.hibernate.cfg.Environment;
 | 
					import org.hibernate.cfg.Environment;
 | 
				
			||||||
import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory;
 | 
					import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory;
 | 
				
			||||||
import org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.springframework.core.io.Resource;
 | 
					import org.springframework.core.io.Resource;
 | 
				
			||||||
import org.springframework.core.io.ResourceLoader;
 | 
					import org.springframework.core.io.ResourceLoader;
 | 
				
			||||||
| 
						 | 
					@ -140,7 +139,7 @@ public class LocalSessionFactoryBuilder extends Configuration {
 | 
				
			||||||
	 * instructing Hibernate to interact with externally managed transactions.
 | 
						 * instructing Hibernate to interact with externally managed transactions.
 | 
				
			||||||
	 * <p>A passed-in Spring {@link JtaTransactionManager} needs to contain a JTA
 | 
						 * <p>A passed-in Spring {@link JtaTransactionManager} needs to contain a JTA
 | 
				
			||||||
	 * {@link TransactionManager} reference to be usable here, except for the WebSphere
 | 
						 * {@link TransactionManager} reference to be usable here, except for the WebSphere
 | 
				
			||||||
	 * case where we'll automatically set {@link WebSphereExtendedJtaPlatform} accordingly.
 | 
						 * case where we'll automatically set {@code WebSphereExtendedJtaPlatform} accordingly.
 | 
				
			||||||
	 * <p>Note: If this is set, the Hibernate settings should not contain a JTA platform
 | 
						 * <p>Note: If this is set, the Hibernate settings should not contain a JTA platform
 | 
				
			||||||
	 * setting to avoid meaningless double configuration.
 | 
						 * setting to avoid meaningless double configuration.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
| 
						 | 
					@ -149,7 +148,8 @@ public class LocalSessionFactoryBuilder extends Configuration {
 | 
				
			||||||
		if (jtaTransactionManager instanceof JtaTransactionManager) {
 | 
							if (jtaTransactionManager instanceof JtaTransactionManager) {
 | 
				
			||||||
			boolean webspherePresent = ClassUtils.isPresent("com.ibm.wsspi.uow.UOWManager", getClass().getClassLoader());
 | 
								boolean webspherePresent = ClassUtils.isPresent("com.ibm.wsspi.uow.UOWManager", getClass().getClassLoader());
 | 
				
			||||||
			if (webspherePresent) {
 | 
								if (webspherePresent) {
 | 
				
			||||||
				getProperties().put(AvailableSettings.JTA_PLATFORM, new WebSphereExtendedJtaPlatform());
 | 
									getProperties().put(AvailableSettings.JTA_PLATFORM,
 | 
				
			||||||
 | 
											ConfigurableJtaPlatform.getJtaPlatformBasePackage() + "internal.WebSphereExtendedJtaPlatform");
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			else {
 | 
								else {
 | 
				
			||||||
				JtaTransactionManager jtaTm = (JtaTransactionManager) jtaTransactionManager;
 | 
									JtaTransactionManager jtaTm = (JtaTransactionManager) jtaTransactionManager;
 | 
				
			||||||
| 
						 | 
					@ -158,12 +158,13 @@ public class LocalSessionFactoryBuilder extends Configuration {
 | 
				
			||||||
							"Can only apply JtaTransactionManager which has a TransactionManager reference set");
 | 
												"Can only apply JtaTransactionManager which has a TransactionManager reference set");
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				getProperties().put(AvailableSettings.JTA_PLATFORM,
 | 
									getProperties().put(AvailableSettings.JTA_PLATFORM,
 | 
				
			||||||
						new ConfigurableJtaPlatform(jtaTm.getTransactionManager(), jtaTm.getUserTransaction()));
 | 
											new ConfigurableJtaPlatform(jtaTm.getTransactionManager(), jtaTm.getUserTransaction(),
 | 
				
			||||||
 | 
													jtaTm.getTransactionSynchronizationRegistry()).getJtaPlatformProxy());
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else if (jtaTransactionManager instanceof TransactionManager) {
 | 
							else if (jtaTransactionManager instanceof TransactionManager) {
 | 
				
			||||||
			getProperties().put(AvailableSettings.JTA_PLATFORM,
 | 
								getProperties().put(AvailableSettings.JTA_PLATFORM,
 | 
				
			||||||
					new ConfigurableJtaPlatform((TransactionManager) jtaTransactionManager, null));
 | 
										new ConfigurableJtaPlatform((TransactionManager) jtaTransactionManager, null, null).getJtaPlatformProxy());
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else {
 | 
							else {
 | 
				
			||||||
			throw new IllegalArgumentException(
 | 
								throw new IllegalArgumentException(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,6 +16,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package org.springframework.orm.hibernate4;
 | 
					package org.springframework.orm.hibernate4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.lang.reflect.Method;
 | 
				
			||||||
import javax.sql.DataSource;
 | 
					import javax.sql.DataSource;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.apache.commons.logging.Log;
 | 
					import org.apache.commons.logging.Log;
 | 
				
			||||||
| 
						 | 
					@ -45,7 +46,7 @@ import org.hibernate.exception.DataException;
 | 
				
			||||||
import org.hibernate.exception.JDBCConnectionException;
 | 
					import org.hibernate.exception.JDBCConnectionException;
 | 
				
			||||||
import org.hibernate.exception.LockAcquisitionException;
 | 
					import org.hibernate.exception.LockAcquisitionException;
 | 
				
			||||||
import org.hibernate.exception.SQLGrammarException;
 | 
					import org.hibernate.exception.SQLGrammarException;
 | 
				
			||||||
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
 | 
					import org.hibernate.service.spi.Wrapped;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.springframework.dao.CannotAcquireLockException;
 | 
					import org.springframework.dao.CannotAcquireLockException;
 | 
				
			||||||
import org.springframework.dao.DataAccessException;
 | 
					import org.springframework.dao.DataAccessException;
 | 
				
			||||||
| 
						 | 
					@ -57,6 +58,8 @@ import org.springframework.dao.InvalidDataAccessApiUsageException;
 | 
				
			||||||
import org.springframework.dao.InvalidDataAccessResourceUsageException;
 | 
					import org.springframework.dao.InvalidDataAccessResourceUsageException;
 | 
				
			||||||
import org.springframework.dao.PessimisticLockingFailureException;
 | 
					import org.springframework.dao.PessimisticLockingFailureException;
 | 
				
			||||||
import org.springframework.jdbc.datasource.DataSourceUtils;
 | 
					import org.springframework.jdbc.datasource.DataSourceUtils;
 | 
				
			||||||
 | 
					import org.springframework.util.ClassUtils;
 | 
				
			||||||
 | 
					import org.springframework.util.ReflectionUtils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Helper class featuring methods for Hibernate Session handling.
 | 
					 * Helper class featuring methods for Hibernate Session handling.
 | 
				
			||||||
| 
						 | 
					@ -83,6 +86,12 @@ public abstract class SessionFactoryUtils {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static final Log logger = LogFactory.getLog(SessionFactoryUtils.class);
 | 
						static final Log logger = LogFactory.getLog(SessionFactoryUtils.class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Bridging between the different ConnectionProvider package location in 4.0-4.2 vs 4.3.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						private static final Method getConnectionProviderMethod =
 | 
				
			||||||
 | 
								ClassUtils.getMethodIfAvailable(SessionFactoryImplementor.class, "getConnectionProvider");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Determine the DataSource of the given SessionFactory.
 | 
						 * Determine the DataSource of the given SessionFactory.
 | 
				
			||||||
| 
						 | 
					@ -91,8 +100,8 @@ public abstract class SessionFactoryUtils {
 | 
				
			||||||
	 * @see org.hibernate.engine.spi.SessionFactoryImplementor#getConnectionProvider
 | 
						 * @see org.hibernate.engine.spi.SessionFactoryImplementor#getConnectionProvider
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public static DataSource getDataSource(SessionFactory sessionFactory) {
 | 
						public static DataSource getDataSource(SessionFactory sessionFactory) {
 | 
				
			||||||
		if (sessionFactory instanceof SessionFactoryImplementor) {
 | 
							if (getConnectionProviderMethod != null && sessionFactory instanceof SessionFactoryImplementor) {
 | 
				
			||||||
			ConnectionProvider cp = ((SessionFactoryImplementor) sessionFactory).getConnectionProvider();
 | 
								Wrapped cp = (Wrapped) ReflectionUtils.invokeMethod(getConnectionProviderMethod, sessionFactory);
 | 
				
			||||||
			return cp.unwrap(DataSource.class);
 | 
								return cp.unwrap(DataSource.class);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return null;
 | 
							return null;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Copyright 2002-2012 the original author or authors.
 | 
					 * Copyright 2002-2013 the original author or authors.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 * you may not use this file except in compliance with the License.
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
| 
						 | 
					@ -16,16 +16,16 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package org.springframework.orm.hibernate4;
 | 
					package org.springframework.orm.hibernate4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import javax.transaction.TransactionManager;
 | 
					import java.lang.reflect.Method;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.hibernate.FlushMode;
 | 
					import org.hibernate.FlushMode;
 | 
				
			||||||
import org.hibernate.HibernateException;
 | 
					import org.hibernate.HibernateException;
 | 
				
			||||||
import org.hibernate.Session;
 | 
					import org.hibernate.Session;
 | 
				
			||||||
import org.hibernate.context.spi.CurrentSessionContext;
 | 
					import org.hibernate.context.spi.CurrentSessionContext;
 | 
				
			||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
 | 
					import org.hibernate.engine.spi.SessionFactoryImplementor;
 | 
				
			||||||
import org.hibernate.service.jta.platform.spi.JtaPlatform;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
 | 
					import org.springframework.transaction.support.TransactionSynchronizationManager;
 | 
				
			||||||
 | 
					import org.springframework.util.ReflectionUtils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Implementation of Hibernate 3.1's CurrentSessionContext interface
 | 
					 * Implementation of Hibernate 3.1's CurrentSessionContext interface
 | 
				
			||||||
| 
						 | 
					@ -44,7 +44,7 @@ public class SpringSessionContext implements CurrentSessionContext {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private final SessionFactoryImplementor sessionFactory;
 | 
						private final SessionFactoryImplementor sessionFactory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private final CurrentSessionContext jtaSessionContext;
 | 
						private CurrentSessionContext jtaSessionContext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
| 
						 | 
					@ -53,9 +53,17 @@ public class SpringSessionContext implements CurrentSessionContext {
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public SpringSessionContext(SessionFactoryImplementor sessionFactory) {
 | 
						public SpringSessionContext(SessionFactoryImplementor sessionFactory) {
 | 
				
			||||||
		this.sessionFactory = sessionFactory;
 | 
							this.sessionFactory = sessionFactory;
 | 
				
			||||||
		JtaPlatform jtaPlatform = sessionFactory.getServiceRegistry().getService(JtaPlatform.class);
 | 
							try {
 | 
				
			||||||
		TransactionManager transactionManager = jtaPlatform.retrieveTransactionManager();
 | 
								Object jtaPlatform = sessionFactory.getServiceRegistry().getService(ConfigurableJtaPlatform.jtaPlatformClass);
 | 
				
			||||||
		this.jtaSessionContext = (transactionManager != null ? new SpringJtaSessionContext(sessionFactory) : null);
 | 
								Method rtmMethod = ConfigurableJtaPlatform.jtaPlatformClass.getMethod("retrieveTransactionManager");
 | 
				
			||||||
 | 
								Object transactionManager = ReflectionUtils.invokeMethod(rtmMethod, jtaPlatform);
 | 
				
			||||||
 | 
								if (transactionManager != null) {
 | 
				
			||||||
 | 
									this.jtaSessionContext = new SpringJtaSessionContext(sessionFactory);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							catch (Exception ex) {
 | 
				
			||||||
 | 
								throw new IllegalStateException("Could not introspect Hibernate JtaPlatform for SpringJtaSessionContext", ex);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,7 +87,7 @@ public class SpringSessionContext implements CurrentSessionContext {
 | 
				
			||||||
				// Switch to FlushMode.AUTO, as we have to assume a thread-bound Session
 | 
									// Switch to FlushMode.AUTO, as we have to assume a thread-bound Session
 | 
				
			||||||
				// with FlushMode.MANUAL, which needs to allow flushing within the transaction.
 | 
									// with FlushMode.MANUAL, which needs to allow flushing within the transaction.
 | 
				
			||||||
				FlushMode flushMode = session.getFlushMode();
 | 
									FlushMode flushMode = session.getFlushMode();
 | 
				
			||||||
				if (FlushMode.isManualFlushMode(flushMode) &&
 | 
									if (flushMode.equals(FlushMode.MANUAL) &&
 | 
				
			||||||
						!TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
 | 
											!TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
 | 
				
			||||||
					session.setFlushMode(FlushMode.AUTO);
 | 
										session.setFlushMode(FlushMode.AUTO);
 | 
				
			||||||
					sessionHolder.setPreviousFlushMode(flushMode);
 | 
										sessionHolder.setPreviousFlushMode(flushMode);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,9 @@ import java.util.ArrayList;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.Properties;
 | 
					import java.util.Properties;
 | 
				
			||||||
import javax.sql.DataSource;
 | 
					import javax.sql.DataSource;
 | 
				
			||||||
 | 
					import javax.transaction.TransactionManager;
 | 
				
			||||||
 | 
					import javax.transaction.TransactionSynchronizationRegistry;
 | 
				
			||||||
 | 
					import javax.transaction.UserTransaction;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.hibernate.FlushMode;
 | 
					import org.hibernate.FlushMode;
 | 
				
			||||||
import org.hibernate.Interceptor;
 | 
					import org.hibernate.Interceptor;
 | 
				
			||||||
| 
						 | 
					@ -32,8 +35,10 @@ import org.hibernate.Session;
 | 
				
			||||||
import org.hibernate.SessionBuilder;
 | 
					import org.hibernate.SessionBuilder;
 | 
				
			||||||
import org.hibernate.SessionFactory;
 | 
					import org.hibernate.SessionFactory;
 | 
				
			||||||
import org.hibernate.Transaction;
 | 
					import org.hibernate.Transaction;
 | 
				
			||||||
 | 
					import org.hibernate.cfg.AvailableSettings;
 | 
				
			||||||
import org.hibernate.dialect.HSQLDialect;
 | 
					import org.hibernate.dialect.HSQLDialect;
 | 
				
			||||||
import org.hibernate.engine.spi.SessionImplementor;
 | 
					import org.hibernate.engine.spi.SessionImplementor;
 | 
				
			||||||
 | 
					import org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory;
 | 
				
			||||||
import org.hibernate.exception.ConstraintViolationException;
 | 
					import org.hibernate.exception.ConstraintViolationException;
 | 
				
			||||||
import org.junit.After;
 | 
					import org.junit.After;
 | 
				
			||||||
import org.junit.Test;
 | 
					import org.junit.Test;
 | 
				
			||||||
| 
						 | 
					@ -49,6 +54,7 @@ import org.springframework.transaction.PlatformTransactionManager;
 | 
				
			||||||
import org.springframework.transaction.TransactionDefinition;
 | 
					import org.springframework.transaction.TransactionDefinition;
 | 
				
			||||||
import org.springframework.transaction.TransactionStatus;
 | 
					import org.springframework.transaction.TransactionStatus;
 | 
				
			||||||
import org.springframework.transaction.UnexpectedRollbackException;
 | 
					import org.springframework.transaction.UnexpectedRollbackException;
 | 
				
			||||||
 | 
					import org.springframework.transaction.jta.JtaTransactionManager;
 | 
				
			||||||
import org.springframework.transaction.support.TransactionCallback;
 | 
					import org.springframework.transaction.support.TransactionCallback;
 | 
				
			||||||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
 | 
					import org.springframework.transaction.support.TransactionCallbackWithoutResult;
 | 
				
			||||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
 | 
					import org.springframework.transaction.support.TransactionSynchronizationManager;
 | 
				
			||||||
| 
						 | 
					@ -1180,6 +1186,37 @@ public class HibernateTransactionManagerTests {
 | 
				
			||||||
		verify(session).close();
 | 
							verify(session).close();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Test
 | 
				
			||||||
 | 
						public void testSetJtaTransactionManager() throws Exception {
 | 
				
			||||||
 | 
							DataSource ds = mock(DataSource.class);
 | 
				
			||||||
 | 
							TransactionManager tm = mock(TransactionManager.class);
 | 
				
			||||||
 | 
							UserTransaction ut = mock(UserTransaction.class);
 | 
				
			||||||
 | 
							TransactionSynchronizationRegistry tsr = mock(TransactionSynchronizationRegistry.class);
 | 
				
			||||||
 | 
							JtaTransactionManager jtm = new JtaTransactionManager();
 | 
				
			||||||
 | 
							jtm.setTransactionManager(tm);
 | 
				
			||||||
 | 
							jtm.setUserTransaction(ut);
 | 
				
			||||||
 | 
							jtm.setTransactionSynchronizationRegistry(tsr);
 | 
				
			||||||
 | 
							LocalSessionFactoryBuilder lsfb = new LocalSessionFactoryBuilder(ds);
 | 
				
			||||||
 | 
							lsfb.setJtaTransactionManager(jtm);
 | 
				
			||||||
 | 
							Object jtaPlatform = lsfb.getProperties().get(AvailableSettings.JTA_PLATFORM);
 | 
				
			||||||
 | 
							assertNotNull(jtaPlatform);
 | 
				
			||||||
 | 
							assertSame(tm, jtaPlatform.getClass().getMethod("retrieveTransactionManager").invoke(jtaPlatform));
 | 
				
			||||||
 | 
							assertSame(ut, jtaPlatform.getClass().getMethod("retrieveUserTransaction").invoke(jtaPlatform));
 | 
				
			||||||
 | 
							assertTrue(lsfb.getProperties().get(AvailableSettings.TRANSACTION_STRATEGY) instanceof CMTTransactionFactory);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Test
 | 
				
			||||||
 | 
						public void testSetTransactionManager() throws Exception {
 | 
				
			||||||
 | 
							DataSource ds = mock(DataSource.class);
 | 
				
			||||||
 | 
							TransactionManager tm = mock(TransactionManager.class);
 | 
				
			||||||
 | 
							LocalSessionFactoryBuilder lsfb = new LocalSessionFactoryBuilder(ds);
 | 
				
			||||||
 | 
							lsfb.setJtaTransactionManager(tm);
 | 
				
			||||||
 | 
							Object jtaPlatform = lsfb.getProperties().get(AvailableSettings.JTA_PLATFORM);
 | 
				
			||||||
 | 
							assertNotNull(jtaPlatform);
 | 
				
			||||||
 | 
							assertSame(tm, jtaPlatform.getClass().getMethod("retrieveTransactionManager").invoke(jtaPlatform));
 | 
				
			||||||
 | 
							assertTrue(lsfb.getProperties().get(AvailableSettings.TRANSACTION_STRATEGY) instanceof CMTTransactionFactory);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public interface ImplementingSession extends Session, SessionImplementor {
 | 
						public interface ImplementingSession extends Session, SessionImplementor {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue