added "jtaTransactionManager" property to Hibernate 4 LocalSessionFactoryBean/Builder
Issue: SPR-9480
This commit is contained in:
parent
9aa43fcef6
commit
dda3197c77
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.hibernate4;
|
||||
|
||||
import javax.transaction.TransactionManager;
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import org.hibernate.service.jta.platform.internal.AbstractJtaPlatform;
|
||||
|
||||
import org.springframework.transaction.jta.UserTransactionAdapter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Implementation of Hibernate 4's {@link org.hibernate.service.jta.platform.spi.JtaPlatform}
|
||||
* SPI, exposing passed-in {@link TransactionManager} and {@link UserTransaction} references.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1.2
|
||||
*/
|
||||
class ConfigurableJtaPlatform extends AbstractJtaPlatform {
|
||||
|
||||
private final TransactionManager transactionManager;
|
||||
|
||||
private final UserTransaction userTransaction;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new ConfigurableJtaPlatform instance with the given
|
||||
* JTA TransactionManager and optionally a given UserTransaction.
|
||||
* @param tm the JTA TransactionManager reference (required)
|
||||
* @param ut the JTA UserTransaction reference (optional)
|
||||
*/
|
||||
public ConfigurableJtaPlatform(TransactionManager tm, UserTransaction ut) {
|
||||
Assert.notNull(tm, "TransactionManager reference must not be null");
|
||||
this.transactionManager = tm;
|
||||
this.userTransaction = (ut != null ? ut : new UserTransactionAdapter(tm));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected TransactionManager locateTransactionManager() {
|
||||
return this.transactionManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UserTransaction locateUserTransaction() {
|
||||
return this.userTransaction;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canCacheTransactionManager() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canCacheUserTransaction() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -48,6 +48,12 @@ import org.springframework.core.io.support.ResourcePatternUtils;
|
|||
* However, in practice, it is closer to <code>AnnotationSessionFactoryBean</code> since
|
||||
* its core purpose is to bootstrap a <code>SessionFactory</code> from annotation scanning.
|
||||
*
|
||||
* <p><b>NOTE:</b> To set up Hibernate 4 for Spring-driven JTA transactions, make
|
||||
* sure to either specify the {@link #setJtaTransactionManager "jtaTransactionManager"}
|
||||
* bean property or to set the "hibernate.transaction.factory_class" property to
|
||||
* {@link org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory}.
|
||||
* Otherwise, Hibernate's smart flushing mechanism won't work properly.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
* @see #setDataSource
|
||||
|
@ -82,6 +88,8 @@ public class LocalSessionFactoryBean extends HibernateExceptionTranslator
|
|||
|
||||
private String[] packagesToScan;
|
||||
|
||||
private Object jtaTransactionManager;
|
||||
|
||||
private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
|
||||
|
||||
private Configuration configuration;
|
||||
|
@ -250,6 +258,16 @@ public class LocalSessionFactoryBean extends HibernateExceptionTranslator
|
|||
this.packagesToScan = packagesToScan;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Spring {@link org.springframework.transaction.jta.JtaTransactionManager}
|
||||
* or the JTA {@link javax.transaction.TransactionManager} to be used with Hibernate,
|
||||
* if any.
|
||||
* @see LocalSessionFactoryBuilder#setJtaTransactionManager
|
||||
*/
|
||||
public void setJtaTransactionManager(Object jtaTransactionManager) {
|
||||
this.jtaTransactionManager = jtaTransactionManager;
|
||||
}
|
||||
|
||||
public void setResourceLoader(ResourceLoader resourceLoader) {
|
||||
this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
|
||||
}
|
||||
|
@ -330,6 +348,10 @@ public class LocalSessionFactoryBean extends HibernateExceptionTranslator
|
|||
sfb.scanPackages(this.packagesToScan);
|
||||
}
|
||||
|
||||
if (this.jtaTransactionManager != null) {
|
||||
sfb.setJtaTransactionManager(this.jtaTransactionManager);
|
||||
}
|
||||
|
||||
// Build SessionFactory instance.
|
||||
this.configuration = sfb;
|
||||
this.sessionFactory = buildSessionFactory(sfb);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -22,12 +22,16 @@ import javax.persistence.Embeddable;
|
|||
import javax.persistence.Entity;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.sql.DataSource;
|
||||
import javax.transaction.TransactionManager;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.cfg.Environment;
|
||||
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.ResourceLoader;
|
||||
|
@ -39,6 +43,8 @@ import org.springframework.core.type.classreading.MetadataReader;
|
|||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.core.type.filter.TypeFilter;
|
||||
import org.springframework.transaction.jta.JtaTransactionManager;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
|
@ -50,6 +56,11 @@ import org.springframework.util.ReflectionUtils;
|
|||
* <p>This is designed for programmatic use, e.g. in {@code @Bean} factory methods.
|
||||
* Consider using {@link LocalSessionFactoryBean} for XML bean definition files.
|
||||
*
|
||||
* <p><b>NOTE:</b> To set up Hibernate 4 for Spring-driven JTA transactions, make
|
||||
* sure to either use the {@link #setJtaTransactionManager} method or to set the
|
||||
* "hibernate.transaction.factory_class" property to {@link CMTTransactionFactory}.
|
||||
* Otherwise, Hibernate's smart flushing mechanism won't work properly.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
* @see LocalSessionFactoryBean
|
||||
|
@ -97,18 +108,60 @@ public class LocalSessionFactoryBuilder extends Configuration {
|
|||
* Create a new LocalSessionFactoryBuilder for the given DataSource.
|
||||
* @param dataSource the JDBC DataSource that the resulting Hibernate SessionFactory should be using
|
||||
* (may be <code>null</code>)
|
||||
* @param classLoader the ResourceLoader to load application classes from
|
||||
* @param resourceLoader the ResourceLoader to load application classes from
|
||||
*/
|
||||
public LocalSessionFactoryBuilder(DataSource dataSource, ResourceLoader resourceLoader) {
|
||||
getProperties().put(Environment.CURRENT_SESSION_CONTEXT_CLASS, SpringSessionContext.class.getName());
|
||||
if (dataSource != null) {
|
||||
getProperties().put(Environment.DATASOURCE, dataSource);
|
||||
}
|
||||
getProperties().put("hibernate.classLoader.application", resourceLoader.getClassLoader());
|
||||
getProperties().put(AvailableSettings.APP_CLASSLOADER, resourceLoader.getClassLoader());
|
||||
this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 4's session and cache synchronization, with the
|
||||
* "hibernate.transaction.jta.platform" automatically set to it. Also sets
|
||||
* "hibernate.transaction.factory_class" to {@link CMTTransactionFactory},
|
||||
* instructing Hibernate to interact with externally managed transactions.
|
||||
* <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 {@link WebSphereExtendedJtaPlatform} accordingly.
|
||||
* <p>Note: If this is set, the Hibernate settings should not contain a JTA platform
|
||||
* setting to avoid meaningless double configuration.
|
||||
*/
|
||||
public LocalSessionFactoryBuilder setJtaTransactionManager(Object jtaTransactionManager) {
|
||||
Assert.notNull(jtaTransactionManager, "Transaction manager reference must not be null");
|
||||
if (jtaTransactionManager instanceof JtaTransactionManager) {
|
||||
boolean webspherePresent = ClassUtils.isPresent("com.ibm.wsspi.uow.UOWManager", getClass().getClassLoader());
|
||||
if (webspherePresent) {
|
||||
getProperties().put(AvailableSettings.JTA_PLATFORM, new WebSphereExtendedJtaPlatform());
|
||||
}
|
||||
else {
|
||||
JtaTransactionManager jtaTm = (JtaTransactionManager) jtaTransactionManager;
|
||||
if (jtaTm.getTransactionManager() == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Can only apply JtaTransactionManager which has a TransactionManager reference set");
|
||||
}
|
||||
getProperties().put(AvailableSettings.JTA_PLATFORM,
|
||||
new ConfigurableJtaPlatform(jtaTm.getTransactionManager(), jtaTm.getUserTransaction()));
|
||||
}
|
||||
}
|
||||
else if (jtaTransactionManager instanceof TransactionManager) {
|
||||
getProperties().put(AvailableSettings.JTA_PLATFORM,
|
||||
new ConfigurableJtaPlatform((TransactionManager) jtaTransactionManager, null));
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException(
|
||||
"Unknown transaction manager type: " + jtaTransactionManager.getClass().getName());
|
||||
}
|
||||
getProperties().put(AvailableSettings.TRANSACTION_STRATEGY, new CMTTransactionFactory());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the given annotated classes in a batch.
|
||||
* @see #addAnnotatedClass
|
||||
|
|
Loading…
Reference in New Issue