diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceTransactionManager.java b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceTransactionManager.java index 9f8ed469a9..3acd77498a 100644 --- a/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceTransactionManager.java +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/datasource/DataSourceTransactionManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 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. @@ -33,10 +33,9 @@ import org.springframework.transaction.support.TransactionSynchronizationManager * {@link org.springframework.transaction.PlatformTransactionManager} * implementation for a single JDBC {@link javax.sql.DataSource}. This class is * capable of working in any environment with any JDBC driver, as long as the setup - * uses a JDBC 2.0 Standard Extensions / JDBC 3.0 {@code javax.sql.DataSource} - * as its Connection factory mechanism. Binds a JDBC Connection from the specified - * DataSource to the current thread, potentially allowing for one thread-bound - * Connection per DataSource. + * uses a {@code javax.sql.DataSource} as its {@code Connection} factory mechanism. + * Binds a JDBC Connection from the specified DataSource to the current thread, + * potentially allowing for one thread-bound Connection per DataSource. * *

Note: The DataSource that this transaction manager operates on needs * to return independent Connections. The Connections may come from a pool @@ -75,8 +74,8 @@ import org.springframework.transaction.support.TransactionSynchronizationManager * an actual JDBC Connection from the target DataSource until a Statement gets executed, * lazily applying the specified transaction settings to the target Connection. * - *

On JDBC 3.0, this transaction manager supports nested transactions via the - * JDBC 3.0 {@link java.sql.Savepoint} mechanism. The + *

This transaction manager supports nested transactions via the JDBC 3.0 + * {@link java.sql.Savepoint} mechanism. The * {@link #setNestedTransactionAllowed "nestedTransactionAllowed"} flag defaults * to "true", since nested transactions will work without restrictions on JDBC * drivers that support savepoints (such as the Oracle JDBC driver). @@ -178,7 +177,7 @@ public class DataSourceTransactionManager extends AbstractPlatformTransactionMan DataSourceTransactionObject txObject = new DataSourceTransactionObject(); txObject.setSavepointAllowed(isNestedTransactionAllowed()); ConnectionHolder conHolder = - (ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource); + (ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource); txObject.setConnectionHolder(conHolder, false); return txObject; } @@ -237,7 +236,10 @@ public class DataSourceTransactionManager extends AbstractPlatformTransactionMan } catch (Throwable ex) { - DataSourceUtils.releaseConnection(con, this.dataSource); + if (txObject.isNewConnectionHolder()) { + DataSourceUtils.releaseConnection(con, this.dataSource); + txObject.setConnectionHolder(null, false); + } throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex); } } diff --git a/spring-jms/src/main/java/org/springframework/jms/connection/JmsTransactionManager.java b/spring-jms/src/main/java/org/springframework/jms/connection/JmsTransactionManager.java index e0d544cbde..7d118e66e1 100644 --- a/spring-jms/src/main/java/org/springframework/jms/connection/JmsTransactionManager.java +++ b/spring-jms/src/main/java/org/springframework/jms/connection/JmsTransactionManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 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. @@ -173,6 +173,7 @@ public class JmsTransactionManager extends AbstractPlatformTransactionManager if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) { throw new InvalidIsolationLevelException("JMS does not support an isolation level concept"); } + JmsTransactionObject txObject = (JmsTransactionObject) transaction; Connection con = null; Session session = null; @@ -188,10 +189,17 @@ public class JmsTransactionManager extends AbstractPlatformTransactionManager if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { txObject.getResourceHolder().setTimeoutInSeconds(timeout); } - TransactionSynchronizationManager.bindResource( - getConnectionFactory(), txObject.getResourceHolder()); + TransactionSynchronizationManager.bindResource(getConnectionFactory(), txObject.getResourceHolder()); } catch (Throwable ex) { + if (session != null) { + try { + session.close(); + } + catch (Throwable ex2) { + // ignore + } + } if (con != null) { try { con.close(); diff --git a/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/HibernateTransactionManager.java b/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/HibernateTransactionManager.java index 81181052d9..9c5bd8ed2c 100644 --- a/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/HibernateTransactionManager.java +++ b/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/HibernateTransactionManager.java @@ -81,12 +81,12 @@ import org.springframework.transaction.support.TransactionSynchronizationManager * transaction. The DataSource that Hibernate uses needs to be JTA-enabled in * such a scenario (see container setup). * - *

On JDBC 3.0, this transaction manager supports nested transactions via JDBC 3.0 - * Savepoints. The {@link #setNestedTransactionAllowed} "nestedTransactionAllowed"} - * flag defaults to "false", though, as nested transactions will just apply to the - * JDBC Connection, not to the Hibernate Session and its cached objects. You can - * manually set the flag to "true" if you want to use nested transactions for - * JDBC access code which participates in Hibernate transactions (provided that + *

This transaction manager supports nested transactions via JDBC 3.0 Savepoints. + * The {@link #setNestedTransactionAllowed} "nestedTransactionAllowed"} flag defaults + * to "false", though, as nested transactions will just apply to the JDBC Connection, + * not to the Hibernate Session and its cached entity objects and related context. + * You can manually set the flag to "true" if you want to use nested transactions + * for JDBC access code which participates in Hibernate transactions (provided that * your JDBC driver supports Savepoints). Note that Hibernate itself does not * support nested transactions! Hence, do not expect Hibernate access code to * semantically participate in a nested transaction. @@ -510,6 +510,7 @@ public class HibernateTransactionManager extends AbstractPlatformTransactionMana } finally { SessionFactoryUtils.closeSession(session); + txObject.setSessionHolder(null); } } throw new CannotCreateTransactionException("Could not open Hibernate Session for transaction", ex); diff --git a/spring-orm/src/main/java/org/springframework/orm/hibernate3/HibernateTransactionManager.java b/spring-orm/src/main/java/org/springframework/orm/hibernate3/HibernateTransactionManager.java index ff7a4163a7..d25df391e8 100644 --- a/spring-orm/src/main/java/org/springframework/orm/hibernate3/HibernateTransactionManager.java +++ b/spring-orm/src/main/java/org/springframework/orm/hibernate3/HibernateTransactionManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 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. @@ -100,12 +100,12 @@ import org.springframework.transaction.support.TransactionSynchronizationManager * special restrictions with EJB CMT and restrictive JTA subsystems: See * {@link org.springframework.transaction.jta.JtaTransactionManager}'s javadoc for details. * - *

On JDBC 3.0, this transaction manager supports nested transactions via JDBC 3.0 - * Savepoints. The {@link #setNestedTransactionAllowed} "nestedTransactionAllowed"} - * flag defaults to "false", though, as nested transactions will just apply to the - * JDBC Connection, not to the Hibernate Session and its cached objects. You can - * manually set the flag to "true" if you want to use nested transactions for - * JDBC access code which participates in Hibernate transactions (provided that + *

This transaction manager supports nested transactions via JDBC 3.0 Savepoints. + * The {@link #setNestedTransactionAllowed} "nestedTransactionAllowed"} flag defaults + * to "false", though, as nested transactions will just apply to the JDBC Connection, + * not to the Hibernate Session and its cached entity objects and related context. + * You can manually set the flag to "true" if you want to use nested transactions + * for JDBC access code which participates in Hibernate transactions (provided that * your JDBC driver supports Savepoints). Note that Hibernate itself does not * support nested transactions! Hence, do not expect Hibernate access code to * semantically participate in a nested transaction. @@ -592,6 +592,7 @@ public class HibernateTransactionManager extends AbstractPlatformTransactionMana } finally { SessionFactoryUtils.closeSession(session); + txObject.setSessionHolder(null); } } throw new CannotCreateTransactionException("Could not open Hibernate Session for transaction", ex); diff --git a/spring-orm/src/main/java/org/springframework/orm/jdo/JdoTransactionManager.java b/spring-orm/src/main/java/org/springframework/orm/jdo/JdoTransactionManager.java index 76ae8146be..b363434152 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jdo/JdoTransactionManager.java +++ b/spring-orm/src/main/java/org/springframework/orm/jdo/JdoTransactionManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2014 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. @@ -40,12 +40,12 @@ import org.springframework.transaction.support.ResourceTransactionManager; import org.springframework.transaction.support.TransactionSynchronizationManager; /** - * {@link org.springframework.transaction.PlatformTransactionManager} implementation - * for a single JDO {@link javax.jdo.PersistenceManagerFactory}. Binds a JDO - * PersistenceManager from the specified factory to the thread, potentially allowing - * for one thread-bound PersistenceManager per factory. - * {@link PersistenceManagerFactoryUtils} and {@link JdoTemplate} are aware of - * thread-bound persistence managers and participate in such transactions automatically. + * {@link org.springframework.transaction.PlatformTransactionManager} implementation for a + * single JDO {@link javax.jdo.PersistenceManagerFactory}. Binds a JDO PersistenceManager + * from the specified factory to the thread, potentially allowing for one thread-bound + * PersistenceManager per factory. {@link PersistenceManagerFactoryUtils} and + * {@link org.springframework.orm.jdo.support.SpringPersistenceManagerProxyBean} are aware + * of thread-bound persistence managers and participate in such transactions automatically. * Using either of those (or going through a {@link TransactionAwarePersistenceManagerFactoryProxy} * is required for JDO access code supporting this transaction management mechanism. * @@ -73,10 +73,10 @@ import org.springframework.transaction.support.TransactionSynchronizationManager * that acts as "connectionFactory" of the PersistenceManagerFactory, so you usually * don't need to explicitly specify the "dataSource" property. * - *

On JDBC 3.0, this transaction manager supports nested transactions via JDBC 3.0 - * Savepoints. The {@link #setNestedTransactionAllowed} "nestedTransactionAllowed"} - * flag defaults to "false", though, as nested transactions will just apply to the - * JDBC Connection, not to the JDO PersistenceManager and its cached objects. + *

This transaction manager supports nested transactions via JDBC 3.0 Savepoints. + * The {@link #setNestedTransactionAllowed} "nestedTransactionAllowed"} flag defaults + * to "false", though, as nested transactions will just apply to the JDBC Connection, + * not to the JDO PersistenceManager and its cached entity objects and related context. * You can manually set the flag to "true" if you want to use nested transactions * for JDBC access code which participates in JDO transactions (provided that your * JDBC driver supports Savepoints). Note that JDO itself does not support @@ -91,7 +91,6 @@ import org.springframework.transaction.support.TransactionSynchronizationManager * @see LocalPersistenceManagerFactoryBean * @see PersistenceManagerFactoryUtils#getPersistenceManager * @see PersistenceManagerFactoryUtils#releasePersistenceManager - * @see JdoTemplate * @see TransactionAwarePersistenceManagerFactoryProxy * @see org.springframework.jdbc.datasource.DataSourceUtils#getConnection * @see org.springframework.jdbc.datasource.DataSourceUtils#releaseConnection @@ -155,7 +154,7 @@ public class JdoTransactionManager extends AbstractPlatformTransactionManager * The DataSource should match the one used by the JDO PersistenceManagerFactory: * for example, you could specify the same JNDI DataSource for both. *

If the PersistenceManagerFactory uses a DataSource as connection factory, - * the DataSource will be autodetected: You can still explictly specify the + * the DataSource will be autodetected: You can still explicitly specify the * DataSource, but you don't need to in this case. *

A transactional JDBC Connection for this DataSource will be provided to * application code accessing this DataSource directly via DataSourceUtils @@ -340,15 +339,16 @@ public class JdoTransactionManager extends AbstractPlatformTransactionManager conHolder.setTimeoutInSeconds(timeoutToUse); } if (logger.isDebugEnabled()) { - logger.debug("Exposing JDO transaction as JDBC transaction [" + conHolder.getConnectionHandle() + "]"); + logger.debug("Exposing JDO transaction as JDBC transaction [" + + conHolder.getConnectionHandle() + "]"); } TransactionSynchronizationManager.bindResource(getDataSource(), conHolder); txObject.setConnectionHolder(conHolder); } else { if (logger.isDebugEnabled()) { - logger.debug("Not exposing JDO transaction [" + pm + "] as JDBC transaction because JdoDialect [" + - getJdoDialect() + "] does not support JDBC Connection retrieval"); + logger.debug("Not exposing JDO transaction [" + pm + "] as JDBC transaction because " + + "JdoDialect [" + getJdoDialect() + "] does not support JDBC Connection retrieval"); } } } @@ -390,6 +390,7 @@ public class JdoTransactionManager extends AbstractPlatformTransactionManager finally { PersistenceManagerFactoryUtils.releasePersistenceManager(pm, getPersistenceManagerFactory()); } + txObject.setPersistenceManagerHolder(null, false); } } @@ -418,7 +419,7 @@ public class JdoTransactionManager extends AbstractPlatformTransactionManager } /** - * This implementation returns "true": a JDO2 commit will properly handle + * This implementation returns "true": a JDO commit will properly handle * transactions that have been marked rollback-only at a global level. */ @Override diff --git a/spring-orm/src/main/java/org/springframework/orm/jpa/JpaTransactionManager.java b/spring-orm/src/main/java/org/springframework/orm/jpa/JpaTransactionManager.java index f6765ac382..e5a99e347c 100644 --- a/spring-orm/src/main/java/org/springframework/orm/jpa/JpaTransactionManager.java +++ b/spring-orm/src/main/java/org/springframework/orm/jpa/JpaTransactionManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2014 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. @@ -55,8 +55,8 @@ import org.springframework.util.CollectionUtils; * {@link org.springframework.transaction.PlatformTransactionManager} implementation * for a single JPA {@link javax.persistence.EntityManagerFactory}. Binds a JPA * EntityManager from the specified factory to the thread, potentially allowing for - * one thread-bound EntityManager per factory. {@link SharedEntityManagerCreator} - * and {@link JpaTemplate} are aware of thread-bound entity managers and participate + * one thread-bound EntityManager per factory. {@link SharedEntityManagerCreator} and + * {@code @PersistenceContext} are aware of thread-bound entity managers and participate * in such transactions automatically. Using either is required for JPA access code * supporting this transaction management mechanism. * @@ -85,10 +85,10 @@ import org.springframework.util.CollectionUtils; * used as known connection factory of the EntityManagerFactory, so you usually * don't need to explicitly specify the "dataSource" property. * - *

On JDBC 3.0, this transaction manager supports nested transactions via JDBC 3.0 - * Savepoints. The {@link #setNestedTransactionAllowed} "nestedTransactionAllowed"} - * flag defaults to "false", though, as nested transactions will just apply to the - * JDBC Connection, not to the JPA EntityManager and its cached objects. + *

This transaction manager supports nested transactions via JDBC 3.0 Savepoints. + * The {@link #setNestedTransactionAllowed} "nestedTransactionAllowed"} flag defaults + * to "false", though, as nested transactions will just apply to the JDBC Connection, + * not to the JPA EntityManager and its cached entity objects and related context. * You can manually set the flag to "true" if you want to use nested transactions * for JDBC access code which participates in JPA transactions (provided that your * JDBC driver supports Savepoints). Note that JPA itself does not support @@ -100,7 +100,6 @@ import org.springframework.util.CollectionUtils; * @see #setEntityManagerFactory * @see #setDataSource * @see LocalEntityManagerFactoryBean - * @see JpaTemplate#execute * @see org.springframework.orm.jpa.support.SharedEntityManagerBean * @see org.springframework.jdbc.datasource.DataSourceUtils#getConnection * @see org.springframework.jdbc.datasource.DataSourceUtils#releaseConnection @@ -329,8 +328,8 @@ public class JpaTransactionManager extends AbstractPlatformTransactionManager TransactionSynchronizationManager.getResource(getEntityManagerFactory()); if (emHolder != null) { if (logger.isDebugEnabled()) { - logger.debug("Found thread-bound EntityManager [" + - emHolder.getEntityManager() + "] for JPA transaction"); + logger.debug("Found thread-bound EntityManager [" + emHolder.getEntityManager() + + "] for JPA transaction"); } txObject.setEntityManagerHolder(emHolder, false); } @@ -398,15 +397,16 @@ public class JpaTransactionManager extends AbstractPlatformTransactionManager conHolder.setTimeoutInSeconds(timeoutToUse); } if (logger.isDebugEnabled()) { - logger.debug("Exposing JPA transaction as JDBC transaction [" + conHolder.getConnectionHandle() + "]"); + logger.debug("Exposing JPA transaction as JDBC transaction [" + + conHolder.getConnectionHandle() + "]"); } TransactionSynchronizationManager.bindResource(getDataSource(), conHolder); txObject.setConnectionHolder(conHolder); } else { if (logger.isDebugEnabled()) { - logger.debug("Not exposing JPA transaction [" + em + "] as JDBC transaction because JpaDialect [" + - getJpaDialect() + "] does not support JDBC Connection retrieval"); + logger.debug("Not exposing JPA transaction [" + em + "] as JDBC transaction because " + + "JpaDialect [" + getJpaDialect() + "] does not support JDBC Connection retrieval"); } } } @@ -465,6 +465,7 @@ public class JpaTransactionManager extends AbstractPlatformTransactionManager finally { EntityManagerFactoryUtils.closeEntityManager(em); } + txObject.setEntityManagerHolder(null, false); } } diff --git a/spring-tx/src/main/java/org/springframework/jca/cci/connection/CciLocalTransactionManager.java b/spring-tx/src/main/java/org/springframework/jca/cci/connection/CciLocalTransactionManager.java index 32eb3ff030..96d4740142 100644 --- a/spring-tx/src/main/java/org/springframework/jca/cci/connection/CciLocalTransactionManager.java +++ b/spring-tx/src/main/java/org/springframework/jca/cci/connection/CciLocalTransactionManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 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. @@ -124,7 +124,7 @@ public class CciLocalTransactionManager extends AbstractPlatformTransactionManag protected Object doGetTransaction() { CciLocalTransactionObject txObject = new CciLocalTransactionObject(); ConnectionHolder conHolder = - (ConnectionHolder) TransactionSynchronizationManager.getResource(getConnectionFactory()); + (ConnectionHolder) TransactionSynchronizationManager.getResource(getConnectionFactory()); txObject.setConnectionHolder(conHolder); return txObject; } @@ -157,7 +157,6 @@ public class CciLocalTransactionManager extends AbstractPlatformTransactionManag } TransactionSynchronizationManager.bindResource(getConnectionFactory(), txObject.getConnectionHolder()); } - catch (NotSupportedException ex) { ConnectionFactoryUtils.releaseConnection(con, getConnectionFactory()); throw new CannotCreateTransactionException("CCI Connection does not support local transactions", ex); @@ -266,7 +265,7 @@ public class CciLocalTransactionManager extends AbstractPlatformTransactionManag } public ConnectionHolder getConnectionHolder() { - return connectionHolder; + return this.connectionHolder; } }