added "flush()" method to TransactionStatus and TransactionSynchronization interfaces; test context manager automatically flushes transactions before rolling back; general polishing of transaction management code
This commit is contained in:
parent
dd7d299aa4
commit
4cc42bf16f
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -345,7 +345,7 @@ public class DataSourceTransactionManager extends AbstractPlatformTransactionMan
|
|||
}
|
||||
|
||||
public boolean isNewConnectionHolder() {
|
||||
return newConnectionHolder;
|
||||
return this.newConnectionHolder;
|
||||
}
|
||||
|
||||
public boolean hasTransaction() {
|
||||
|
|
@ -357,7 +357,7 @@ public class DataSourceTransactionManager extends AbstractPlatformTransactionMan
|
|||
}
|
||||
|
||||
public boolean isMustRestoreAutoCommit() {
|
||||
return mustRestoreAutoCommit;
|
||||
return this.mustRestoreAutoCommit;
|
||||
}
|
||||
|
||||
public void setRollbackOnly() {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -87,6 +87,10 @@ public abstract class JdbcTransactionObjectSupport implements SavepointManager,
|
|||
return this.savepointAllowed;
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Implementation of SavepointManager
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -1958,6 +1958,9 @@ public class DataSourceTransactionManagerTests extends TestCase {
|
|||
public void resume() {
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
}
|
||||
|
||||
public void beforeCommit(boolean readOnly) {
|
||||
if (this.status != TransactionSynchronization.STATUS_COMMITTED) {
|
||||
fail("Should never be called");
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -30,7 +30,6 @@ import javax.jms.TopicSession;
|
|||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.transaction.support.ResourceHolder;
|
||||
import org.springframework.transaction.support.ResourceHolderSynchronization;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
|
@ -387,7 +386,7 @@ public abstract class ConnectionFactoryUtils {
|
|||
* (e.g. when participating in a JtaTransactionManager transaction).
|
||||
* @see org.springframework.transaction.jta.JtaTransactionManager
|
||||
*/
|
||||
private static class JmsResourceSynchronization extends ResourceHolderSynchronization {
|
||||
private static class JmsResourceSynchronization extends ResourceHolderSynchronization<JmsResourceHolder, Object> {
|
||||
|
||||
private final boolean transacted;
|
||||
|
||||
|
|
@ -400,17 +399,17 @@ public abstract class ConnectionFactoryUtils {
|
|||
return !this.transacted;
|
||||
}
|
||||
|
||||
protected void processResourceAfterCommit(ResourceHolder resourceHolder) {
|
||||
protected void processResourceAfterCommit(JmsResourceHolder resourceHolder) {
|
||||
try {
|
||||
((JmsResourceHolder) resourceHolder).commitAll();
|
||||
resourceHolder.commitAll();
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new SynchedLocalTransactionFailedException("Local JMS transaction failed to commit", ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected void releaseResource(ResourceHolder resourceHolder, Object resourceKey) {
|
||||
((JmsResourceHolder) resourceHolder).closeAll();
|
||||
protected void releaseResource(JmsResourceHolder resourceHolder, Object resourceKey) {
|
||||
resourceHolder.closeAll();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -316,6 +316,10 @@ public class JmsTransactionManager extends AbstractPlatformTransactionManager
|
|||
public boolean isRollbackOnly() {
|
||||
return this.resourceHolder.isRollbackOnly();
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -1160,21 +1160,20 @@ public class HibernateTemplate extends HibernateAccessor implements HibernateOpe
|
|||
/**
|
||||
* Check whether write operations are allowed on the given Session.
|
||||
* <p>Default implementation throws an InvalidDataAccessApiUsageException in
|
||||
* case of <code>FlushMode.NEVER/MANUAL</code>. Can be overridden in subclasses.
|
||||
* case of <code>FlushMode.MANUAL</code>. Can be overridden in subclasses.
|
||||
* @param session current Hibernate Session
|
||||
* @throws InvalidDataAccessApiUsageException if write operations are not allowed
|
||||
* @see #setCheckWriteOperations
|
||||
* @see #getFlushMode()
|
||||
* @see #FLUSH_EAGER
|
||||
* @see org.hibernate.Session#getFlushMode()
|
||||
* @see org.hibernate.FlushMode#NEVER
|
||||
* @see org.hibernate.FlushMode#MANUAL
|
||||
*/
|
||||
protected void checkWriteOperationAllowed(Session session) throws InvalidDataAccessApiUsageException {
|
||||
if (isCheckWriteOperations() && getFlushMode() != FLUSH_EAGER &&
|
||||
session.getFlushMode().lessThan(FlushMode.COMMIT)) {
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
"Write operations are not allowed in read-only mode (FlushMode.NEVER/MANUAL): "+
|
||||
"Write operations are not allowed in read-only mode (FlushMode.MANUAL): "+
|
||||
"Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -828,7 +828,7 @@ public class HibernateTransactionManager extends AbstractPlatformTransactionMana
|
|||
* Hibernate transaction object, representing a SessionHolder.
|
||||
* Used as transaction object by HibernateTransactionManager.
|
||||
*/
|
||||
private static class HibernateTransactionObject extends JdbcTransactionObjectSupport {
|
||||
private class HibernateTransactionObject extends JdbcTransactionObjectSupport {
|
||||
|
||||
private SessionHolder sessionHolder;
|
||||
|
||||
|
|
@ -875,16 +875,25 @@ public class HibernateTransactionManager extends AbstractPlatformTransactionMana
|
|||
}
|
||||
|
||||
public void setRollbackOnly() {
|
||||
getSessionHolder().setRollbackOnly();
|
||||
this.sessionHolder.setRollbackOnly();
|
||||
if (hasConnectionHolder()) {
|
||||
getConnectionHolder().setRollbackOnly();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRollbackOnly() {
|
||||
return getSessionHolder().isRollbackOnly() ||
|
||||
return this.sessionHolder.isRollbackOnly() ||
|
||||
(hasConnectionHolder() && getConnectionHolder().isRollbackOnly());
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
try {
|
||||
this.sessionHolder.getSession().flush();
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
throw convertHibernateAccessException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2009 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,6 +124,16 @@ class SpringSessionSynchronization implements TransactionSynchronization, Ordere
|
|||
}
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
try {
|
||||
SessionFactoryUtils.logger.debug("Flushing Hibernate Session on explicit request");
|
||||
getCurrentSession().flush();
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
throw translateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void beforeCommit(boolean readOnly) throws DataAccessException {
|
||||
if (!readOnly) {
|
||||
Session session = getCurrentSession();
|
||||
|
|
@ -135,17 +145,21 @@ class SpringSessionSynchronization implements TransactionSynchronization, Ordere
|
|||
session.flush();
|
||||
}
|
||||
catch (HibernateException ex) {
|
||||
if (this.jdbcExceptionTranslator != null && ex instanceof JDBCException) {
|
||||
JDBCException jdbcEx = (JDBCException) ex;
|
||||
throw this.jdbcExceptionTranslator.translate(
|
||||
"Hibernate flushing: " + jdbcEx.getMessage(), jdbcEx.getSQL(), jdbcEx.getSQLException());
|
||||
}
|
||||
throw SessionFactoryUtils.convertHibernateAccessException(ex);
|
||||
throw translateException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private DataAccessException translateException(HibernateException ex) {
|
||||
if (this.jdbcExceptionTranslator != null && ex instanceof JDBCException) {
|
||||
JDBCException jdbcEx = (JDBCException) ex;
|
||||
return this.jdbcExceptionTranslator.translate(
|
||||
"Hibernate flushing: " + jdbcEx.getMessage(), jdbcEx.getSQL(), jdbcEx.getSQLException());
|
||||
}
|
||||
return SessionFactoryUtils.convertHibernateAccessException(ex);
|
||||
}
|
||||
|
||||
public void beforeCompletion() {
|
||||
if (this.jtaTransaction != null) {
|
||||
// Typically in case of a suspended JTA transaction:
|
||||
|
|
|
|||
|
|
@ -144,10 +144,10 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter {
|
|||
* {@link org.hibernate.Session}. Only applied in single session mode.
|
||||
* <p>Can be populated with the corresponding constant name in XML bean
|
||||
* definitions: e.g. "AUTO".
|
||||
* <p>The default is "NEVER". Specify "AUTO" if you intend to use
|
||||
* <p>The default is "MANUAL". Specify "AUTO" if you intend to use
|
||||
* this filter without service layer transactions.
|
||||
* @see org.hibernate.Session#setFlushMode
|
||||
* @see org.hibernate.FlushMode#NEVER
|
||||
* @see org.hibernate.FlushMode#MANUAL
|
||||
* @see org.hibernate.FlushMode#AUTO
|
||||
*/
|
||||
public void setFlushMode(FlushMode flushMode) {
|
||||
|
|
@ -247,14 +247,14 @@ public class OpenSessionInViewFilter extends OncePerRequestFilter {
|
|||
* Note that this just applies in single session mode!
|
||||
* <p>The default implementation delegates to the
|
||||
* <code>SessionFactoryUtils.getSession</code> method and
|
||||
* sets the <code>Session</code>'s flush mode to "NEVER".
|
||||
* sets the <code>Session</code>'s flush mode to "MANUAL".
|
||||
* <p>Can be overridden in subclasses for creating a Session with a
|
||||
* custom entity interceptor or JDBC exception translator.
|
||||
* @param sessionFactory the SessionFactory that this filter uses
|
||||
* @return the Session to use
|
||||
* @throws DataAccessResourceFailureException if the Session could not be created
|
||||
* @see org.springframework.orm.hibernate3.SessionFactoryUtils#getSession(SessionFactory, boolean)
|
||||
* @see org.hibernate.FlushMode#NEVER
|
||||
* @see org.hibernate.FlushMode#MANUAL
|
||||
*/
|
||||
protected Session getSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException {
|
||||
Session session = SessionFactoryUtils.getSession(sessionFactory, true);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -503,7 +503,7 @@ public class JdoTransactionManager extends AbstractPlatformTransactionManager
|
|||
/**
|
||||
* Convert the given JDOException to an appropriate exception from the
|
||||
* <code>org.springframework.dao</code> hierarchy.
|
||||
* <p>Default implementation delegates to the JdoDialect.
|
||||
* <p>The default implementation delegates to the JdoDialect.
|
||||
* May be overridden in subclasses.
|
||||
* @param ex JDOException that occured
|
||||
* @return the corresponding DataAccessException instance
|
||||
|
|
@ -518,7 +518,7 @@ public class JdoTransactionManager extends AbstractPlatformTransactionManager
|
|||
* JDO transaction object, representing a PersistenceManagerHolder.
|
||||
* Used as transaction object by JdoTransactionManager.
|
||||
*/
|
||||
private static class JdoTransactionObject extends JdbcTransactionObjectSupport {
|
||||
private class JdoTransactionObject extends JdbcTransactionObjectSupport {
|
||||
|
||||
private PersistenceManagerHolder persistenceManagerHolder;
|
||||
|
||||
|
|
@ -533,11 +533,11 @@ public class JdoTransactionManager extends AbstractPlatformTransactionManager
|
|||
}
|
||||
|
||||
public PersistenceManagerHolder getPersistenceManagerHolder() {
|
||||
return persistenceManagerHolder;
|
||||
return this.persistenceManagerHolder;
|
||||
}
|
||||
|
||||
public boolean isNewPersistenceManagerHolder() {
|
||||
return newPersistenceManagerHolder;
|
||||
return this.newPersistenceManagerHolder;
|
||||
}
|
||||
|
||||
public boolean hasTransaction() {
|
||||
|
|
@ -550,7 +550,7 @@ public class JdoTransactionManager extends AbstractPlatformTransactionManager
|
|||
}
|
||||
|
||||
public Object getTransactionData() {
|
||||
return transactionData;
|
||||
return this.transactionData;
|
||||
}
|
||||
|
||||
public void setRollbackOnly() {
|
||||
|
|
@ -567,6 +567,15 @@ public class JdoTransactionManager extends AbstractPlatformTransactionManager
|
|||
Transaction tx = this.persistenceManagerHolder.getPersistenceManager().currentTransaction();
|
||||
return tx.getRollbackOnly();
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
try {
|
||||
this.persistenceManagerHolder.getPersistenceManager().flush();
|
||||
}
|
||||
catch (JDOException ex) {
|
||||
throw convertJdoAccessException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ import org.springframework.jdbc.datasource.DataSourceUtils;
|
|||
import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator;
|
||||
import org.springframework.jdbc.support.SQLExceptionTranslator;
|
||||
import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
|
||||
import org.springframework.transaction.support.ResourceHolder;
|
||||
import org.springframework.transaction.support.ResourceHolderSynchronization;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
|
@ -293,7 +292,8 @@ public abstract class PersistenceManagerFactoryUtils {
|
|||
* (e.g. when participating in a JtaTransactionManager transaction).
|
||||
* @see org.springframework.transaction.jta.JtaTransactionManager
|
||||
*/
|
||||
private static class PersistenceManagerSynchronization extends ResourceHolderSynchronization
|
||||
private static class PersistenceManagerSynchronization
|
||||
extends ResourceHolderSynchronization<PersistenceManagerHolder, PersistenceManagerFactory>
|
||||
implements Ordered {
|
||||
|
||||
private final boolean newPersistenceManager;
|
||||
|
|
@ -308,15 +308,24 @@ public abstract class PersistenceManagerFactoryUtils {
|
|||
return PERSISTENCE_MANAGER_SYNCHRONIZATION_ORDER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushResource(PersistenceManagerHolder resourceHolder) {
|
||||
try {
|
||||
resourceHolder.getPersistenceManager().flush();
|
||||
}
|
||||
catch (JDOException ex) {
|
||||
throw convertJdoAccessException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldUnbindAtCompletion() {
|
||||
return this.newPersistenceManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void releaseResource(ResourceHolder resourceHolder, Object resourceKey) {
|
||||
releasePersistenceManager(((PersistenceManagerHolder) resourceHolder).getPersistenceManager(),
|
||||
(PersistenceManagerFactory) resourceKey);
|
||||
protected void releaseResource(PersistenceManagerHolder resourceHolder, PersistenceManagerFactory resourceKey) {
|
||||
releasePersistenceManager(resourceHolder.getPersistenceManager(), resourceKey);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -105,7 +105,7 @@ public abstract class EntityManagerFactoryUtils {
|
|||
}
|
||||
// No matching persistence unit found - simply take the EntityManagerFactory
|
||||
// with the persistence unit name as bean name (by convention).
|
||||
return (EntityManagerFactory) beanFactory.getBean(unitName, EntityManagerFactory.class);
|
||||
return beanFactory.getBean(unitName, EntityManagerFactory.class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -345,41 +345,62 @@ public abstract class EntityManagerFactoryUtils {
|
|||
* (e.g. when participating in a JtaTransactionManager transaction).
|
||||
* @see org.springframework.transaction.jta.JtaTransactionManager
|
||||
*/
|
||||
private static class EntityManagerSynchronization extends ResourceHolderSynchronization implements Ordered {
|
||||
private static class EntityManagerSynchronization
|
||||
extends ResourceHolderSynchronization<EntityManagerHolder, EntityManagerFactory>
|
||||
implements Ordered {
|
||||
|
||||
private final Object transactionData;
|
||||
|
||||
private final JpaDialect jpaDialect;
|
||||
|
||||
private final boolean newEntityManager;
|
||||
|
||||
public EntityManagerSynchronization(
|
||||
EntityManagerHolder emHolder, EntityManagerFactory emf, Object transactionData, boolean newEntityManager) {
|
||||
EntityManagerHolder emHolder, EntityManagerFactory emf, Object txData, boolean newEm) {
|
||||
super(emHolder, emf);
|
||||
this.transactionData = transactionData;
|
||||
this.newEntityManager = newEntityManager;
|
||||
this.transactionData = txData;
|
||||
this.jpaDialect = (emf instanceof EntityManagerFactoryInfo ?
|
||||
((EntityManagerFactoryInfo) emf).getJpaDialect() : null);
|
||||
this.newEntityManager = newEm;
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
return ENTITY_MANAGER_SYNCHRONIZATION_ORDER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void flushResource(EntityManagerHolder resourceHolder) {
|
||||
try {
|
||||
resourceHolder.getEntityManager().flush();
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
if (this.jpaDialect != null) {
|
||||
throw this.jpaDialect.translateExceptionIfPossible(ex);
|
||||
}
|
||||
else {
|
||||
throw convertJpaAccessExceptionIfPossible(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldUnbindAtCompletion() {
|
||||
return this.newEntityManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void releaseResource(ResourceHolder resourceHolder, Object resourceKey) {
|
||||
closeEntityManager(((EntityManagerHolder) resourceHolder).getEntityManager());
|
||||
protected void releaseResource(EntityManagerHolder resourceHolder, EntityManagerFactory resourceKey) {
|
||||
closeEntityManager(resourceHolder.getEntityManager());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void cleanupResource(ResourceHolder resourceHolder, Object resourceKey, boolean committed) {
|
||||
protected void cleanupResource(EntityManagerHolder resourceHolder, EntityManagerFactory resourceKey, boolean committed) {
|
||||
if (!committed) {
|
||||
// Clear all pending inserts/updates/deletes in the EntityManager.
|
||||
// Necessary for pre-bound EntityManagers, to avoid inconsistent state.
|
||||
((EntityManagerHolder) resourceHolder).getEntityManager().clear();
|
||||
resourceHolder.getEntityManager().clear();
|
||||
}
|
||||
cleanupTransaction(this.transactionData, (EntityManagerFactory) resourceKey);
|
||||
cleanupTransaction(this.transactionData, resourceKey);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -436,7 +436,8 @@ public abstract class ExtendedEntityManagerCreator {
|
|||
* TransactionSynchronization enlisting an extended EntityManager
|
||||
* with a current Spring transaction.
|
||||
*/
|
||||
private static class ExtendedEntityManagerSynchronization extends ResourceHolderSynchronization
|
||||
private static class ExtendedEntityManagerSynchronization
|
||||
extends ResourceHolderSynchronization<EntityManagerHolder, EntityManager>
|
||||
implements Ordered {
|
||||
|
||||
private final EntityManager entityManager;
|
||||
|
|
@ -454,6 +455,16 @@ public abstract class ExtendedEntityManagerCreator {
|
|||
return EntityManagerFactoryUtils.ENTITY_MANAGER_SYNCHRONIZATION_ORDER + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void flushResource(EntityManagerHolder resourceHolder) {
|
||||
try {
|
||||
this.entityManager.flush();
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
throw convertException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldReleaseBeforeCompletion() {
|
||||
return false;
|
||||
|
|
@ -467,7 +478,7 @@ public abstract class ExtendedEntityManagerCreator {
|
|||
this.entityManager.getTransaction().commit();
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
throw convertCompletionException(ex);
|
||||
throw convertException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -480,12 +491,12 @@ public abstract class ExtendedEntityManagerCreator {
|
|||
this.entityManager.getTransaction().rollback();
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
throw convertCompletionException(ex);
|
||||
throw convertException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private RuntimeException convertCompletionException(RuntimeException ex) {
|
||||
private RuntimeException convertException(RuntimeException ex) {
|
||||
DataAccessException daex = (this.exceptionTranslator != null) ?
|
||||
this.exceptionTranslator.translateExceptionIfPossible(ex) :
|
||||
EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(ex);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -19,7 +19,6 @@ package org.springframework.orm.jpa;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.EntityTransaction;
|
||||
|
|
@ -553,7 +552,7 @@ public class JpaTransactionManager extends AbstractPlatformTransactionManager
|
|||
* JPA transaction object, representing a EntityManagerHolder.
|
||||
* Used as transaction object by JpaTransactionManager.
|
||||
*/
|
||||
private static class JpaTransactionObject extends JdbcTransactionObjectSupport {
|
||||
private class JpaTransactionObject extends JdbcTransactionObjectSupport {
|
||||
|
||||
private EntityManagerHolder entityManagerHolder;
|
||||
|
||||
|
|
@ -606,6 +605,15 @@ public class JpaTransactionManager extends AbstractPlatformTransactionManager
|
|||
return tx.getRollbackOnly();
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
try {
|
||||
this.entityManagerHolder.getEntityManager().flush();
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
throw DataAccessUtils.translateIfNecessary(ex, getJpaDialect());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object createSavepoint() throws TransactionException {
|
||||
return getSavepointManager().createSavepoint();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -18,7 +18,6 @@ package org.springframework.orm.hibernate3;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.transaction.RollbackException;
|
||||
import javax.transaction.Status;
|
||||
import javax.transaction.Synchronization;
|
||||
|
|
@ -108,7 +107,7 @@ public class HibernateJtaTransactionTests extends TestCase {
|
|||
session.createQuery("some query string");
|
||||
sessionControl.setReturnValue(query, 1);
|
||||
if (readOnly) {
|
||||
session.setFlushMode(FlushMode.NEVER);
|
||||
session.setFlushMode(FlushMode.MANUAL);
|
||||
sessionControl.setVoidCallable(1);
|
||||
}
|
||||
query.list();
|
||||
|
|
@ -370,6 +369,14 @@ public class HibernateJtaTransactionTests extends TestCase {
|
|||
}
|
||||
|
||||
public void testJtaTransactionRollback() throws Exception {
|
||||
doTestJtaTransactionRollback(false);
|
||||
}
|
||||
|
||||
public void testJtaTransactionRollbackWithFlush() throws Exception {
|
||||
doTestJtaTransactionRollback(true);
|
||||
}
|
||||
|
||||
private void doTestJtaTransactionRollback(final boolean flush) throws Exception {
|
||||
MockControl utControl = MockControl.createControl(UserTransaction.class);
|
||||
UserTransaction ut = (UserTransaction) utControl.getMock();
|
||||
ut.getStatus();
|
||||
|
|
@ -390,6 +397,10 @@ public class HibernateJtaTransactionTests extends TestCase {
|
|||
sfControl.setReturnValue(session, 1);
|
||||
session.getSessionFactory();
|
||||
sessionControl.setReturnValue(sf, 1);
|
||||
if (flush) {
|
||||
session.flush();
|
||||
sessionControl.setVoidCallable(1);
|
||||
}
|
||||
sfControl.replay();
|
||||
sessionControl.replay();
|
||||
|
||||
|
|
@ -409,6 +420,9 @@ public class HibernateJtaTransactionTests extends TestCase {
|
|||
return l;
|
||||
}
|
||||
});
|
||||
if (flush) {
|
||||
status.flush();
|
||||
}
|
||||
status.setRollbackOnly();
|
||||
sessionControl.verify();
|
||||
sessionControl.reset();
|
||||
|
|
@ -495,7 +509,7 @@ public class HibernateJtaTransactionTests extends TestCase {
|
|||
sessionControl.setReturnValue(true, 5);
|
||||
session.getFlushMode();
|
||||
if (flushNever) {
|
||||
sessionControl.setReturnValue(FlushMode.NEVER, 1);
|
||||
sessionControl.setReturnValue(FlushMode.MANUAL, 1);
|
||||
if (!readOnly) {
|
||||
session.setFlushMode(FlushMode.AUTO);
|
||||
sessionControl.setVoidCallable(1);
|
||||
|
|
@ -546,7 +560,7 @@ public class HibernateJtaTransactionTests extends TestCase {
|
|||
session.flush();
|
||||
sessionControl.setVoidCallable(1);
|
||||
if (flushNever) {
|
||||
session.setFlushMode(FlushMode.NEVER);
|
||||
session.setFlushMode(FlushMode.MANUAL);
|
||||
sessionControl.setVoidCallable(1);
|
||||
}
|
||||
}
|
||||
|
|
@ -1064,15 +1078,15 @@ public class HibernateJtaTransactionTests extends TestCase {
|
|||
session.getSessionFactory();
|
||||
sessionControl.setReturnValue(sf, 1);
|
||||
session.getFlushMode();
|
||||
sessionControl.setReturnValue(FlushMode.NEVER, 1);
|
||||
sessionControl.setReturnValue(FlushMode.MANUAL, 1);
|
||||
session.setFlushMode(FlushMode.AUTO);
|
||||
sessionControl.setVoidCallable(1);
|
||||
session.flush();
|
||||
sessionControl.setVoidCallable(1);
|
||||
session.setFlushMode(FlushMode.NEVER);
|
||||
session.setFlushMode(FlushMode.MANUAL);
|
||||
sessionControl.setVoidCallable(1);
|
||||
session.getFlushMode();
|
||||
sessionControl.setReturnValue(FlushMode.NEVER, 1);
|
||||
sessionControl.setReturnValue(FlushMode.MANUAL, 1);
|
||||
session.close();
|
||||
sessionControl.setReturnValue(null, 1);
|
||||
sfControl.replay();
|
||||
|
|
@ -1306,7 +1320,7 @@ public class HibernateJtaTransactionTests extends TestCase {
|
|||
sfControl.setReturnValue(tm, 7);
|
||||
session.isOpen();
|
||||
sessionControl.setReturnValue(true, 8);
|
||||
session.setFlushMode(FlushMode.NEVER);
|
||||
session.setFlushMode(FlushMode.MANUAL);
|
||||
sessionControl.setVoidCallable(1);
|
||||
session.close();
|
||||
sessionControl.setReturnValue(null, 2);
|
||||
|
|
@ -1667,7 +1681,7 @@ public class HibernateJtaTransactionTests extends TestCase {
|
|||
sessionControl.setReturnValue(true, 5);
|
||||
session.getFlushMode();
|
||||
if (flushNever) {
|
||||
sessionControl.setReturnValue(FlushMode.NEVER, 1);
|
||||
sessionControl.setReturnValue(FlushMode.MANUAL, 1);
|
||||
session.setFlushMode(FlushMode.AUTO);
|
||||
sessionControl.setVoidCallable(1);
|
||||
}
|
||||
|
|
@ -1702,7 +1716,7 @@ public class HibernateJtaTransactionTests extends TestCase {
|
|||
session.flush();
|
||||
sessionControl.setVoidCallable(1);
|
||||
if (flushNever) {
|
||||
session.setFlushMode(FlushMode.NEVER);
|
||||
session.setFlushMode(FlushMode.MANUAL);
|
||||
sessionControl.setVoidCallable(1);
|
||||
}
|
||||
session.disconnect();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -1779,6 +1779,51 @@ public class HibernateTransactionManagerTests extends TestCase {
|
|||
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
|
||||
}
|
||||
|
||||
public void testTransactionFlush() throws Exception {
|
||||
MockControl sfControl = MockControl.createControl(SessionFactory.class);
|
||||
final SessionFactory sf = (SessionFactory) sfControl.getMock();
|
||||
MockControl sessionControl = MockControl.createControl(Session.class);
|
||||
final Session session = (Session) sessionControl.getMock();
|
||||
MockControl txControl = MockControl.createControl(Transaction.class);
|
||||
Transaction tx = (Transaction) txControl.getMock();
|
||||
|
||||
sf.openSession();
|
||||
sfControl.setReturnValue(session, 1);
|
||||
session.beginTransaction();
|
||||
sessionControl.setReturnValue(tx, 1);
|
||||
session.flush();
|
||||
sessionControl.setVoidCallable(1);
|
||||
tx.commit();
|
||||
txControl.setVoidCallable(1);
|
||||
session.close();
|
||||
sessionControl.setReturnValue(null, 1);
|
||||
|
||||
sfControl.replay();
|
||||
sessionControl.replay();
|
||||
txControl.replay();
|
||||
|
||||
HibernateTransactionManager tm = new HibernateTransactionManager(sf);
|
||||
tm.setPrepareConnection(false);
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
|
||||
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
|
||||
|
||||
tt.execute(new TransactionCallbackWithoutResult() {
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
assertTrue("Has thread session", TransactionSynchronizationManager.hasResource(sf));
|
||||
assertFalse(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
|
||||
assertTrue(TransactionSynchronizationManager.isActualTransactionActive());
|
||||
status.flush();
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue("Hasn't thread session", !TransactionSynchronizationManager.hasResource(sf));
|
||||
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
|
||||
sfControl.verify();
|
||||
sessionControl.verify();
|
||||
txControl.verify();
|
||||
}
|
||||
|
||||
protected void tearDown() {
|
||||
assertTrue(TransactionSynchronizationManager.getResourceMap().isEmpty());
|
||||
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -1222,4 +1222,41 @@ public class JdoTransactionManagerTests extends TestCase {
|
|||
queryControl.verify();
|
||||
}
|
||||
|
||||
public void testTransactionFlush() {
|
||||
pmf.getConnectionFactory();
|
||||
pmfControl.setReturnValue(null, 1);
|
||||
pmf.getPersistenceManager();
|
||||
pmfControl.setReturnValue(pm, 1);
|
||||
pm.currentTransaction();
|
||||
pmControl.setReturnValue(tx, 3);
|
||||
pm.flush();
|
||||
pmControl.setVoidCallable(1);
|
||||
pm.close();
|
||||
pmControl.setVoidCallable(1);
|
||||
tx.begin();
|
||||
txControl.setVoidCallable(1);
|
||||
tx.getRollbackOnly();
|
||||
txControl.setReturnValue(false, 1);
|
||||
tx.commit();
|
||||
txControl.setVoidCallable(1);
|
||||
pmfControl.replay();
|
||||
pmControl.replay();
|
||||
txControl.replay();
|
||||
|
||||
PlatformTransactionManager tm = new JdoTransactionManager(pmf);
|
||||
TransactionTemplate tt = new TransactionTemplate(tm);
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
|
||||
|
||||
tt.execute(new TransactionCallbackWithoutResult() {
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
assertTrue("Has thread pm", TransactionSynchronizationManager.hasResource(pmf));
|
||||
status.flush();
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue("Hasn't thread pm", !TransactionSynchronizationManager.hasResource(pmf));
|
||||
assertTrue("JTA synchronizations not active", !TransactionSynchronizationManager.isSynchronizationActive());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -18,7 +18,6 @@ package org.springframework.orm.jpa;
|
|||
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityNotFoundException;
|
||||
import javax.persistence.FlushModeType;
|
||||
|
|
@ -95,9 +94,8 @@ public abstract class AbstractContainerEntityManagerFactoryIntegrationTests
|
|||
Person notThere = sharedEntityManager.getReference(Person.class, 666);
|
||||
|
||||
// We may get here (as with Hibernate).
|
||||
// Either behaviour is
|
||||
// valid--throw exception on first access
|
||||
// or on getReference itself
|
||||
// Either behaviour is valid: throw exception on first access
|
||||
// or on getReference itself.
|
||||
notThere.getFirstName();
|
||||
}
|
||||
|
||||
|
|
@ -175,8 +173,7 @@ public abstract class AbstractContainerEntityManagerFactoryIntegrationTests
|
|||
}
|
||||
|
||||
protected void testInstantiateAndSave(EntityManager em) {
|
||||
assertEquals("Should be no people from previous transactions",
|
||||
0, countRowsInTable("person"));
|
||||
assertEquals("Should be no people from previous transactions", 0, countRowsInTable("person"));
|
||||
Person p = new Person();
|
||||
p.setFirstName("Tony");
|
||||
p.setLastName("Blair");
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -93,13 +93,11 @@ public class ApplicationManagedEntityManagerIntegrationTests extends AbstractEnt
|
|||
em.persist(p);
|
||||
|
||||
em.flush();
|
||||
assertEquals("1 row must have been inserted",
|
||||
1, countRowsInTable("person"));
|
||||
assertEquals("1 row must have been inserted", 1, countRowsInTable("person"));
|
||||
}
|
||||
|
||||
public void testStateClean() {
|
||||
assertEquals("Should be no people from previous transactions",
|
||||
0, countRowsInTable("person"));
|
||||
assertEquals("Should be no people from previous transactions", 0, countRowsInTable("person"));
|
||||
}
|
||||
|
||||
public void testReuseInNewTransaction() {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -114,8 +114,7 @@ public class ContainerManagedEntityManagerIntegrationTests extends AbstractEntit
|
|||
em.persist(p);
|
||||
|
||||
em.flush();
|
||||
assertEquals("1 row must have been inserted",
|
||||
1, countRowsInTable("person"));
|
||||
assertEquals("1 row must have been inserted", 1, countRowsInTable("person"));
|
||||
}
|
||||
|
||||
public void testReuseInNewTransaction() {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -1071,4 +1071,33 @@ public class JpaTransactionManagerTests extends TestCase {
|
|||
txControl.verify();
|
||||
}
|
||||
|
||||
public void testTransactionFlush() {
|
||||
managerControl.expectAndReturn(manager.getTransaction(), tx);
|
||||
txControl.expectAndReturn(tx.getRollbackOnly(), false);
|
||||
managerControl.expectAndReturn(manager.getTransaction(), tx);
|
||||
tx.commit();
|
||||
manager.flush();
|
||||
|
||||
factoryControl.replay();
|
||||
managerControl.replay();
|
||||
txControl.replay();
|
||||
|
||||
assertTrue(!TransactionSynchronizationManager.hasResource(factory));
|
||||
assertTrue(!TransactionSynchronizationManager.isSynchronizationActive());
|
||||
|
||||
tt.execute(new TransactionCallbackWithoutResult() {
|
||||
public void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
assertTrue(TransactionSynchronizationManager.hasResource(factory));
|
||||
status.flush();
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue(!TransactionSynchronizationManager.hasResource(factory));
|
||||
assertTrue(!TransactionSynchronizationManager.isSynchronizationActive());
|
||||
|
||||
factoryControl.verify();
|
||||
managerControl.verify();
|
||||
txControl.verify();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -335,15 +335,15 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis
|
|||
if (rollbackAnnotation != null) {
|
||||
boolean rollbackOverride = rollbackAnnotation.value();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Method-level @Rollback(" + rollbackOverride + ") overrides default rollback [" + rollback
|
||||
+ "] for test context [" + testContext + "]");
|
||||
logger.debug("Method-level @Rollback(" + rollbackOverride + ") overrides default rollback [" +
|
||||
rollback + "] for test context [" + testContext + "]");
|
||||
}
|
||||
rollback = rollbackOverride;
|
||||
}
|
||||
else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("No method-level @Rollback override: using default rollback [" + rollback
|
||||
+ "] for test context [" + testContext + "]");
|
||||
logger.debug("No method-level @Rollback override: using default rollback [" +
|
||||
rollback + "] for test context [" + testContext + "]");
|
||||
}
|
||||
}
|
||||
return rollback;
|
||||
|
|
@ -498,6 +498,7 @@ public class TransactionalTestExecutionListener extends AbstractTestExecutionLis
|
|||
|
||||
public void endTransaction(boolean rollback) {
|
||||
if (rollback) {
|
||||
this.transactionStatus.flush();
|
||||
this.transactionManager.rollback(this.transactionStatus);
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -25,7 +25,6 @@ import org.apache.commons.logging.Log;
|
|||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.jca.cci.CannotGetCciConnectionException;
|
||||
import org.springframework.transaction.support.ResourceHolder;
|
||||
import org.springframework.transaction.support.ResourceHolderSynchronization;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
|
@ -199,15 +198,16 @@ public abstract class ConnectionFactoryUtils {
|
|||
* Callback for resource cleanup at the end of a non-native CCI transaction
|
||||
* (e.g. when participating in a JTA transaction).
|
||||
*/
|
||||
private static class ConnectionSynchronization extends ResourceHolderSynchronization {
|
||||
private static class ConnectionSynchronization
|
||||
extends ResourceHolderSynchronization<ConnectionHolder, ConnectionFactory> {
|
||||
|
||||
public ConnectionSynchronization(ConnectionHolder connectionHolder, ConnectionFactory connectionFactory) {
|
||||
super(connectionHolder, connectionFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void releaseResource(ResourceHolder resourceHolder, Object resourceKey) {
|
||||
releaseConnection(((ConnectionHolder) resourceHolder).getConnection(), (ConnectionFactory) resourceKey);
|
||||
protected void releaseResource(ConnectionHolder resourceHolder, ConnectionFactory resourceKey) {
|
||||
releaseConnection(resourceHolder.getConnection(), resourceKey);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -75,6 +75,12 @@ public interface TransactionStatus extends SavepointManager {
|
|||
*/
|
||||
boolean isRollbackOnly();
|
||||
|
||||
/**
|
||||
* Flush the underlying session to the datastore, if applicable:
|
||||
* for example, all affected Hibernate/JPA sessions.
|
||||
*/
|
||||
void flush();
|
||||
|
||||
/**
|
||||
* Return whether this transaction is completed, that is,
|
||||
* whether it has already been committed or rolled back.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2009 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,6 +22,7 @@ import javax.transaction.UserTransaction;
|
|||
|
||||
import org.springframework.transaction.TransactionSystemException;
|
||||
import org.springframework.transaction.support.SmartTransactionObject;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationUtils;
|
||||
|
||||
/**
|
||||
* JTA transaction object, representing a {@link javax.transaction.UserTransaction}.
|
||||
|
|
@ -72,4 +73,13 @@ public class JtaTransactionObject implements SmartTransactionObject {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation triggers flush callbacks,
|
||||
* assuming that they will flush all affected ORM sessions.
|
||||
* @see org.springframework.transaction.support.TransactionSynchronization#flush()
|
||||
*/
|
||||
public void flush() {
|
||||
TransactionSynchronizationUtils.triggerFlush();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -89,6 +89,12 @@ public abstract class AbstractTransactionStatus implements TransactionStatus {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementations is empty, considering flush as a no-op.
|
||||
*/
|
||||
public void flush() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark this transaction as completed, that is, committed or rolled back.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -145,7 +145,7 @@ public class DefaultTransactionStatus extends AbstractTransactionStatus {
|
|||
|
||||
/**
|
||||
* Determine the rollback-only flag via checking both the transaction object,
|
||||
* provided that the latter implements the SmartTransactionObject interface.
|
||||
* provided that the latter implements the {@link SmartTransactionObject} interface.
|
||||
* <p>Will return "true" if the transaction itself has been marked rollback-only
|
||||
* by the transaction coordinator, for example in case of a timeout.
|
||||
* @see SmartTransactionObject#isRollbackOnly
|
||||
|
|
@ -156,6 +156,16 @@ public class DefaultTransactionStatus extends AbstractTransactionStatus {
|
|||
((SmartTransactionObject) this.transaction).isRollbackOnly());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegate the flushing to the transaction object,
|
||||
* provided that the latter implements the {@link SmartTransactionObject} interface.
|
||||
*/
|
||||
public void flush() {
|
||||
if (this.transaction instanceof SmartTransactionObject) {
|
||||
((SmartTransactionObject) this.transaction).flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation exposes the SavepointManager interface
|
||||
* of the underlying transaction object, if any.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -23,11 +23,12 @@ package org.springframework.transaction.support;
|
|||
* @author Juergen Hoeller
|
||||
* @since 2.5.5
|
||||
*/
|
||||
public class ResourceHolderSynchronization implements TransactionSynchronization {
|
||||
public abstract class ResourceHolderSynchronization<H extends ResourceHolder, K>
|
||||
implements TransactionSynchronization {
|
||||
|
||||
private final ResourceHolder resourceHolder;
|
||||
private final H resourceHolder;
|
||||
|
||||
private final Object resourceKey;
|
||||
private final K resourceKey;
|
||||
|
||||
private volatile boolean holderActive = true;
|
||||
|
||||
|
|
@ -38,7 +39,7 @@ public class ResourceHolderSynchronization implements TransactionSynchronization
|
|||
* @param resourceKey the key to bind the ResourceHolder for
|
||||
* @see TransactionSynchronizationManager#bindResource
|
||||
*/
|
||||
public ResourceHolderSynchronization(ResourceHolder resourceHolder, Object resourceKey) {
|
||||
public ResourceHolderSynchronization(H resourceHolder, K resourceKey) {
|
||||
this.resourceHolder = resourceHolder;
|
||||
this.resourceKey = resourceKey;
|
||||
}
|
||||
|
|
@ -56,6 +57,10 @@ public class ResourceHolderSynchronization implements TransactionSynchronization
|
|||
}
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
flushResource(this.resourceHolder);
|
||||
}
|
||||
|
||||
public void beforeCommit(boolean readOnly) {
|
||||
}
|
||||
|
||||
|
|
@ -123,13 +128,20 @@ public class ResourceHolderSynchronization implements TransactionSynchronization
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush callback for the given resource holder.
|
||||
* @param resourceHolder the resource holder to flush
|
||||
*/
|
||||
protected void flushResource(H resourceHolder) {
|
||||
}
|
||||
|
||||
/**
|
||||
* After-commit callback for the given resource holder.
|
||||
* Only called when the resource hasn't been released yet
|
||||
* ({@link #shouldReleaseBeforeCompletion()}).
|
||||
* @param resourceHolder the resource holder to process
|
||||
*/
|
||||
protected void processResourceAfterCommit(ResourceHolder resourceHolder) {
|
||||
protected void processResourceAfterCommit(H resourceHolder) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -137,7 +149,7 @@ public class ResourceHolderSynchronization implements TransactionSynchronization
|
|||
* @param resourceHolder the resource holder to process
|
||||
* @param resourceKey the key that the ResourceHolder was bound for
|
||||
*/
|
||||
protected void releaseResource(ResourceHolder resourceHolder, Object resourceKey) {
|
||||
protected void releaseResource(H resourceHolder, K resourceKey) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -147,7 +159,7 @@ public class ResourceHolderSynchronization implements TransactionSynchronization
|
|||
* @param committed whether the transaction has committed (<code>true</code>)
|
||||
* or rolled back (<code>false</code>)
|
||||
*/
|
||||
protected void cleanupResource(ResourceHolder resourceHolder, Object resourceKey, boolean committed) {
|
||||
protected void cleanupResource(H resourceHolder, K resourceKey, boolean committed) {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -41,7 +41,7 @@ public class SimpleTransactionStatus extends AbstractTransactionStatus {
|
|||
|
||||
|
||||
/**
|
||||
* Creates a new instance of the {@link SimpleTransactionStatus} class,
|
||||
* Create a new instance of the {@link SimpleTransactionStatus} class,
|
||||
* indicating a new transaction.
|
||||
*/
|
||||
public SimpleTransactionStatus() {
|
||||
|
|
@ -49,7 +49,7 @@ public class SimpleTransactionStatus extends AbstractTransactionStatus {
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of the {@link SimpleTransactionStatus} class.
|
||||
* Create a new instance of the {@link SimpleTransactionStatus} class.
|
||||
* @param newTransaction whether to indicate a new transaction
|
||||
*/
|
||||
public SimpleTransactionStatus(boolean newTransaction) {
|
||||
|
|
@ -58,7 +58,7 @@ public class SimpleTransactionStatus extends AbstractTransactionStatus {
|
|||
|
||||
|
||||
public boolean isNewTransaction() {
|
||||
return newTransaction;
|
||||
return this.newTransaction;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2005 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -39,4 +39,10 @@ public interface SmartTransactionObject {
|
|||
*/
|
||||
boolean isRollbackOnly();
|
||||
|
||||
/**
|
||||
* Flush the underlying sessions to the datastore, if applicable:
|
||||
* for example, all affected Hibernate/JPA sessions.
|
||||
*/
|
||||
void flush();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
* Copyright 2002-2005 the original author or authors.
|
||||
*
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -27,7 +27,7 @@ import org.springframework.transaction.TransactionStatus;
|
|||
* @since 28.03.2003
|
||||
* @see TransactionTemplate
|
||||
*/
|
||||
public abstract class TransactionCallbackWithoutResult implements TransactionCallback {
|
||||
public abstract class TransactionCallbackWithoutResult implements TransactionCallback<Object> {
|
||||
|
||||
public final Object doInTransaction(TransactionStatus status) {
|
||||
doInTransactionWithoutResult(status);
|
||||
|
|
@ -35,10 +35,10 @@ public abstract class TransactionCallbackWithoutResult implements TransactionCal
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets called by TransactionTemplate.execute within a transactional context.
|
||||
* Does not need to care about transactions itself, although it can retrieve
|
||||
* and influence the status of the current transaction via the given status
|
||||
* object, e.g. setting rollback-only.
|
||||
* Gets called by <code>TransactionTemplate.execute</code> within a transactional
|
||||
* context. Does not need to care about transactions itself, although it can retrieve
|
||||
* and influence the status of the current transaction via the given status object,
|
||||
* e.g. setting rollback-only.
|
||||
*
|
||||
* <p>A RuntimeException thrown by the callback is treated as application
|
||||
* exception that enforces a rollback. An exception gets propagated to the
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -60,6 +60,13 @@ public interface TransactionSynchronization {
|
|||
*/
|
||||
void resume();
|
||||
|
||||
/**
|
||||
* Flush the underlying session to the datastore, if applicable:
|
||||
* for example, a Hibernate/JPA session.
|
||||
* @see org.springframework.transaction.TransactionStatus#flush()
|
||||
*/
|
||||
void flush();
|
||||
|
||||
/**
|
||||
* Invoked before transaction commit (before "beforeCompletion").
|
||||
* Can e.g. flush transactional O/R Mapping sessions to the database.
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
*
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -42,6 +42,9 @@ public abstract class TransactionSynchronizationAdapter implements TransactionSy
|
|||
public void resume() {
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
}
|
||||
|
||||
public void beforeCommit(boolean readOnly) {
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2009 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.
|
||||
|
|
@ -59,6 +59,17 @@ public abstract class TransactionSynchronizationUtils {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Trigger <code>flush</code> callbacks on all currently registered synchronizations.
|
||||
* @throws RuntimeException if thrown by a <code>flush</code> callback
|
||||
* @see TransactionSynchronization#flush()
|
||||
*/
|
||||
public static void triggerFlush() {
|
||||
for (TransactionSynchronization synchronization : TransactionSynchronizationManager.getSynchronizations()) {
|
||||
synchronization.flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger <code>beforeCommit</code> callbacks on all currently registered synchronizations.
|
||||
* @param readOnly whether the transaction is defined as read-only transaction
|
||||
|
|
@ -121,7 +132,7 @@ public abstract class TransactionSynchronizationUtils {
|
|||
* @see TransactionSynchronization#STATUS_UNKNOWN
|
||||
*/
|
||||
public static void triggerAfterCompletion(int completionStatus) {
|
||||
List synchronizations = TransactionSynchronizationManager.getSynchronizations();
|
||||
List<TransactionSynchronization> synchronizations = TransactionSynchronizationManager.getSynchronizations();
|
||||
invokeAfterCompletion(synchronizations, completionStatus);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue