Consistent reset of resource holders on doBegin failure
Issue: SPR-12280
(cherry picked from commit 9758bc7)
This commit is contained in:
parent
6183e83b6a
commit
76ab5b9de2
|
|
@ -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.
|
||||
*
|
||||
* <p><b>Note: The DataSource that this transaction manager operates on needs
|
||||
* to return independent Connections.</b> 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.
|
||||
*
|
||||
* <p>On JDBC 3.0, this transaction manager supports nested transactions via the
|
||||
* JDBC 3.0 {@link java.sql.Savepoint} mechanism. The
|
||||
* <p>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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
*
|
||||
* <p>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
|
||||
* <p>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). <i>Note that Hibernate itself does not
|
||||
* support nested transactions! Hence, do not expect Hibernate access code to
|
||||
* semantically participate in a nested transaction.</i>
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
* <p>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
|
||||
* <p>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). <i>Note that Hibernate itself does not
|
||||
* support nested transactions! Hence, do not expect Hibernate access code to
|
||||
* semantically participate in a nested transaction.</i>
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
* <p>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.
|
||||
* <p>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). <i>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.
|
||||
* <p>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.
|
||||
* <p>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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
* <p>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.
|
||||
* <p>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). <i>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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue