diff --git a/hibernate-core/src/main/java/org/hibernate/engine/SessionImplementor.java b/hibernate-core/src/main/java/org/hibernate/engine/SessionImplementor.java index 39a6da32a5..fa921f8e97 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/SessionImplementor.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/SessionImplementor.java @@ -70,6 +70,15 @@ public interface SessionImplementor extends Serializable { */ public void setAutoClear(boolean enabled); + /** + * Disable automatic transaction joining. The really only has any effect for CMT transactions. The default + * Hibernate behavior is to auto join any active JTA transaction (register {@link javax.transaction.Synchronization}). + * JPA however defines an explicit join transaction operation. + * + * See javax.persistence.EntityManager#joinTransaction + */ + public void disableTransactionAutoJoin(); + /** * Does this Session have an active Hibernate transaction * or is there a JTA transaction in progress? diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/TransactionCoordinatorImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/TransactionCoordinatorImpl.java index 00353457b2..3c38be44c5 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/TransactionCoordinatorImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/internal/TransactionCoordinatorImpl.java @@ -115,6 +115,10 @@ public class TransactionCoordinatorImpl implements TransactionCoordinator { currentHibernateTransaction.invalidate(); } currentHibernateTransaction = transactionFactory().createTransaction( this ); + if ( transactionContext.shouldAutoJoinTransaction() ) { + currentHibernateTransaction.markForJoin(); + currentHibernateTransaction.join(); + } // IMPL NOTE : reset clears synchronizations (following jta spec), but not observers! synchronizationRegistry.clearSynchronizations(); diff --git a/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/TransactionContext.java b/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/TransactionContext.java index 7737980758..85be89fd6e 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/TransactionContext.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/transaction/spi/TransactionContext.java @@ -50,6 +50,14 @@ public interface TransactionContext extends Serializable { */ public ConnectionReleaseMode getConnectionReleaseMode(); + /** + * Should transactions be auto joined? Generally this is only a concern for CMT transactions. The default + * should be to auto join. JPA defines an explicit operation for joining a CMT transaction. + * + * @return Should we automatically join transactions + */ + public boolean shouldAutoJoinTransaction(); + /** * Should session automatically be closed after transaction completion in this context? * diff --git a/hibernate-core/src/main/java/org/hibernate/impl/SessionImpl.java b/hibernate-core/src/main/java/org/hibernate/impl/SessionImpl.java index a6a59d6841..1b8429f9ee 100644 --- a/hibernate-core/src/main/java/org/hibernate/impl/SessionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/impl/SessionImpl.java @@ -180,6 +180,7 @@ public final class SessionImpl private transient CacheMode cacheMode = CacheMode.NORMAL; private transient EntityMode entityMode = EntityMode.POJO; private transient boolean autoClear; //for EJB3 + private transient boolean autoJoinTransactions = true; private transient int dontFlushFromFind = 0; private transient boolean flushBeforeCompletionEnabled; @@ -347,6 +348,11 @@ public final class SessionImpl return connectionReleaseMode; } + @Override + public boolean shouldAutoJoinTransaction() { + return autoJoinTransactions; + } + public boolean isAutoCloseSessionEnabled() { return autoCloseSessionEnabled; } @@ -369,7 +375,7 @@ public final class SessionImpl LOG.trace("Skipping auto-flush due to session closed"); return; } - LOG.trace("Automatically flushing session"); + LOG.trace( "Automatically flushing session" ); flush(); if ( childSessionsByEntityMode != null ) { @@ -517,7 +523,7 @@ public final class SessionImpl } public void managedClose() { - LOG.trace("Automatically closing session"); + LOG.trace( "Automatically closing session" ); close(); } @@ -556,6 +562,12 @@ public final class SessionImpl autoClear = enabled; } + @Override + public void disableTransactionAutoJoin() { + errorIfClosed(); + autoJoinTransactions = false; + } + /** * Check if there is a Hibernate or JTA transaction in progress and, * if there is not, flush if necessary, make sure the connection has @@ -2096,6 +2108,7 @@ public final class SessionImpl connectionReleaseMode = ConnectionReleaseMode.parse( ( String ) ois.readObject() ); entityMode = EntityMode.parse( ( String ) ois.readObject() ); autoClear = ois.readBoolean(); + autoJoinTransactions = ois.readBoolean(); flushMode = FlushMode.parse( ( String ) ois.readObject() ); cacheMode = CacheMode.parse( ( String ) ois.readObject() ); flushBeforeCompletionEnabled = ois.readBoolean(); @@ -2155,6 +2168,7 @@ public final class SessionImpl oos.writeObject( connectionReleaseMode.toString() ); oos.writeObject( entityMode.toString() ); oos.writeBoolean( autoClear ); + oos.writeBoolean( autoJoinTransactions ); oos.writeObject( flushMode.toString() ); oos.writeObject( cacheMode.toString() ); oos.writeBoolean( flushBeforeCompletionEnabled ); diff --git a/hibernate-core/src/main/java/org/hibernate/impl/StatelessSessionImpl.java b/hibernate-core/src/main/java/org/hibernate/impl/StatelessSessionImpl.java index fd532d05e2..c582845464 100755 --- a/hibernate-core/src/main/java/org/hibernate/impl/StatelessSessionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/impl/StatelessSessionImpl.java @@ -314,6 +314,11 @@ public class StatelessSessionImpl extends AbstractSessionImpl implements Statele return factory.getSettings().getConnectionReleaseMode(); } + @Override + public boolean shouldAutoJoinTransaction() { + return true; + } + public boolean isAutoCloseSessionEnabled() { return factory.getSettings().isAutoCloseSessionEnabled(); } @@ -472,6 +477,11 @@ public class StatelessSessionImpl extends AbstractSessionImpl implements Statele throw new UnsupportedOperationException(); } + @Override + public void disableTransactionAutoJoin() { + throw new UnsupportedOperationException(); + } + public void setCacheMode(CacheMode cm) { throw new UnsupportedOperationException(); } diff --git a/hibernate-core/src/test/java/org/hibernate/test/common/TransactionContextImpl.java b/hibernate-core/src/test/java/org/hibernate/test/common/TransactionContextImpl.java index 1557f81995..549294c789 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/common/TransactionContextImpl.java +++ b/hibernate-core/src/test/java/org/hibernate/test/common/TransactionContextImpl.java @@ -48,6 +48,11 @@ public class TransactionContextImpl implements TransactionContext { return transactionEnvironment.getTransactionFactory().getDefaultReleaseMode(); } + @Override + public boolean shouldAutoJoinTransaction() { + return true; + } + @Override public boolean isAutoCloseSessionEnabled() { return false; diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java index 680bb185de..98f5a1b5b1 100755 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/AbstractEntityManagerImpl.java @@ -154,6 +154,10 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage } } + public PersistenceUnitTransactionType getTransactionType() { + return transactionType; + } + protected void postInit() { //register in Sync if needed if ( PersistenceUnitTransactionType.JTA.equals( transactionType ) ) { diff --git a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/EntityManagerImpl.java b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/EntityManagerImpl.java index e13a91a0a9..6bf31ff5d9 100755 --- a/hibernate-entitymanager/src/main/java/org/hibernate/ejb/EntityManagerImpl.java +++ b/hibernate-entitymanager/src/main/java/org/hibernate/ejb/EntityManagerImpl.java @@ -113,6 +113,9 @@ public class EntityManagerImpl extends AbstractEntityManagerImpl { if ( persistenceContextType == PersistenceContextType.TRANSACTION ) { ( (SessionImplementor) session ).setAutoClear( true ); } + if ( getTransactionType() == PersistenceUnitTransactionType.JTA ) { + ( (SessionImplementor) session ).disableTransactionAutoJoin(); + } } return session; } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/entities/mapper/relation/lazy/AbstractDelegateSessionImplementor.java b/hibernate-envers/src/main/java/org/hibernate/envers/entities/mapper/relation/lazy/AbstractDelegateSessionImplementor.java index c1c83b57f4..f914b69217 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/entities/mapper/relation/lazy/AbstractDelegateSessionImplementor.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/entities/mapper/relation/lazy/AbstractDelegateSessionImplementor.java @@ -82,7 +82,12 @@ public abstract class AbstractDelegateSessionImplementor implements SessionImple delegate.setAutoClear(enabled); } - public boolean isTransactionInProgress() { + @Override + public void disableTransactionAutoJoin() { + delegate.disableTransactionAutoJoin(); + } + + public boolean isTransactionInProgress() { return delegate.isTransactionInProgress(); }