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
|
* However, in practice, it is closer to <code>AnnotationSessionFactoryBean</code> since
|
||||||
* its core purpose is to bootstrap a <code>SessionFactory</code> from annotation scanning.
|
* 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
|
* @author Juergen Hoeller
|
||||||
* @since 3.1
|
* @since 3.1
|
||||||
* @see #setDataSource
|
* @see #setDataSource
|
||||||
|
@ -82,6 +88,8 @@ public class LocalSessionFactoryBean extends HibernateExceptionTranslator
|
||||||
|
|
||||||
private String[] packagesToScan;
|
private String[] packagesToScan;
|
||||||
|
|
||||||
|
private Object jtaTransactionManager;
|
||||||
|
|
||||||
private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
|
private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
|
||||||
|
|
||||||
private Configuration configuration;
|
private Configuration configuration;
|
||||||
|
@ -250,6 +258,16 @@ public class LocalSessionFactoryBean extends HibernateExceptionTranslator
|
||||||
this.packagesToScan = packagesToScan;
|
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) {
|
public void setResourceLoader(ResourceLoader resourceLoader) {
|
||||||
this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
|
this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
|
||||||
}
|
}
|
||||||
|
@ -330,6 +348,10 @@ public class LocalSessionFactoryBean extends HibernateExceptionTranslator
|
||||||
sfb.scanPackages(this.packagesToScan);
|
sfb.scanPackages(this.packagesToScan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.jtaTransactionManager != null) {
|
||||||
|
sfb.setJtaTransactionManager(this.jtaTransactionManager);
|
||||||
|
}
|
||||||
|
|
||||||
// Build SessionFactory instance.
|
// Build SessionFactory instance.
|
||||||
this.configuration = sfb;
|
this.configuration = sfb;
|
||||||
this.sessionFactory = buildSessionFactory(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");
|
* 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.
|
||||||
|
@ -22,12 +22,16 @@ import javax.persistence.Embeddable;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.MappedSuperclass;
|
import javax.persistence.MappedSuperclass;
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
import javax.transaction.TransactionManager;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.MappingException;
|
import org.hibernate.MappingException;
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
|
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.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;
|
||||||
|
@ -39,6 +43,8 @@ import org.springframework.core.type.classreading.MetadataReader;
|
||||||
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
import org.springframework.core.type.classreading.MetadataReaderFactory;
|
||||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||||
import org.springframework.core.type.filter.TypeFilter;
|
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.ClassUtils;
|
||||||
import org.springframework.util.ReflectionUtils;
|
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.
|
* <p>This is designed for programmatic use, e.g. in {@code @Bean} factory methods.
|
||||||
* Consider using {@link LocalSessionFactoryBean} for XML bean definition files.
|
* 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
|
* @author Juergen Hoeller
|
||||||
* @since 3.1
|
* @since 3.1
|
||||||
* @see LocalSessionFactoryBean
|
* @see LocalSessionFactoryBean
|
||||||
|
@ -97,18 +108,60 @@ public class LocalSessionFactoryBuilder extends Configuration {
|
||||||
* Create a new LocalSessionFactoryBuilder for the given DataSource.
|
* Create a new LocalSessionFactoryBuilder for the given DataSource.
|
||||||
* @param dataSource the JDBC DataSource that the resulting Hibernate SessionFactory should be using
|
* @param dataSource the JDBC DataSource that the resulting Hibernate SessionFactory should be using
|
||||||
* (may be <code>null</code>)
|
* (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) {
|
public LocalSessionFactoryBuilder(DataSource dataSource, ResourceLoader resourceLoader) {
|
||||||
getProperties().put(Environment.CURRENT_SESSION_CONTEXT_CLASS, SpringSessionContext.class.getName());
|
getProperties().put(Environment.CURRENT_SESSION_CONTEXT_CLASS, SpringSessionContext.class.getName());
|
||||||
if (dataSource != null) {
|
if (dataSource != null) {
|
||||||
getProperties().put(Environment.DATASOURCE, dataSource);
|
getProperties().put(Environment.DATASOURCE, dataSource);
|
||||||
}
|
}
|
||||||
getProperties().put("hibernate.classLoader.application", resourceLoader.getClassLoader());
|
getProperties().put(AvailableSettings.APP_CLASSLOADER, resourceLoader.getClassLoader());
|
||||||
this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
|
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.
|
* Add the given annotated classes in a batch.
|
||||||
* @see #addAnnotatedClass
|
* @see #addAnnotatedClass
|
||||||
|
|
Loading…
Reference in New Issue