HHH-7451 - Integrate Draft 7 of the JPA 2.1 spec : SynchronizationType

This commit is contained in:
Steve Ebersole 2012-07-17 17:44:12 -05:00
parent f8d06216e5
commit 6a65c3e7e6
9 changed files with 356 additions and 68 deletions

View File

@ -218,10 +218,15 @@ public class TransactionCoordinatorImpl implements TransactionCoordinator {
return; return;
} }
if ( ! transactionContext.shouldAutoJoinTransaction() ) { if ( currentHibernateTransaction.getJoinStatus() != JoinStatus.JOINED ) {
if ( currentHibernateTransaction.getJoinStatus() != JoinStatus.MARKED_FOR_JOINED ) { // the transaction is not (yet) joined, see if we should join...
LOG.debug( "Skipping JTA sync registration due to auto join checking" ); if ( ! transactionContext.shouldAutoJoinTransaction() ) {
return; // we are supposed to not auto join transactions; if the transaction is not marked for join
// we cannot go any further in attempting to join (register sync).
if ( currentHibernateTransaction.getJoinStatus() != JoinStatus.MARKED_FOR_JOINED ) {
LOG.debug( "Skipping JTA sync registration due to auto join checking" );
return;
}
} }
} }

View File

@ -24,6 +24,7 @@
package org.hibernate.ejb; package org.hibernate.ejb;
import javax.persistence.PersistenceContextType; import javax.persistence.PersistenceContextType;
import javax.persistence.SynchronizationType;
import javax.persistence.spi.PersistenceUnitTransactionType; import javax.persistence.spi.PersistenceUnitTransactionType;
import java.io.Serializable; import java.io.Serializable;
import java.util.Map; import java.util.Map;
@ -41,8 +42,9 @@ public abstract class AbstractEntityManagerImpl
protected AbstractEntityManagerImpl( protected AbstractEntityManagerImpl(
EntityManagerFactoryImpl entityManagerFactory, EntityManagerFactoryImpl entityManagerFactory,
PersistenceContextType type, PersistenceContextType type,
SynchronizationType synchronizationType,
PersistenceUnitTransactionType transactionType, PersistenceUnitTransactionType transactionType,
Map properties) { Map properties) {
super( entityManagerFactory, type, transactionType, properties ); super( entityManagerFactory, type, synchronizationType, transactionType, properties );
} }
} }

View File

@ -47,8 +47,13 @@ public class CriteriaUpdateImpl<T> extends AbstractManipulationCriteriaQuery<T>
} }
@Override @Override
@SuppressWarnings("unchecked")
public <Y, X extends Y> CriteriaUpdate<T> set(SingularAttribute<? super T, Y> singularAttribute, X value) { public <Y, X extends Y> CriteriaUpdate<T> set(SingularAttribute<? super T, Y> singularAttribute, X value) {
addAssignment( getRoot().get( singularAttribute ), criteriaBuilder().literal( value ) ); final Path<Y> attributePath = getRoot().get( singularAttribute );
final Expression valueExpression = value == null
? criteriaBuilder().nullLiteral( attributePath.getJavaType() )
: criteriaBuilder().literal( value );
addAssignment( attributePath, valueExpression );
return this; return this;
} }
@ -61,8 +66,12 @@ public class CriteriaUpdateImpl<T> extends AbstractManipulationCriteriaQuery<T>
} }
@Override @Override
@SuppressWarnings("unchecked")
public <Y, X extends Y> CriteriaUpdate<T> set(Path<Y> attributePath, X value) { public <Y, X extends Y> CriteriaUpdate<T> set(Path<Y> attributePath, X value) {
addAssignment( attributePath, criteriaBuilder().literal( value ) ); final Expression valueExpression = value == null
? criteriaBuilder().nullLiteral( attributePath.getJavaType() )
: criteriaBuilder().literal( value );
addAssignment( attributePath, valueExpression );
return this; return this;
} }
@ -73,8 +82,13 @@ public class CriteriaUpdateImpl<T> extends AbstractManipulationCriteriaQuery<T>
} }
@Override @Override
@SuppressWarnings("unchecked")
public CriteriaUpdate<T> set(String attributeName, Object value) { public CriteriaUpdate<T> set(String attributeName, Object value) {
addAssignment( getRoot().get( attributeName ), criteriaBuilder().literal( value ) ); final Path attributePath = getRoot().get( attributeName );
final Expression valueExpression = value == null
? criteriaBuilder().nullLiteral( attributePath.getJavaType() )
: criteriaBuilder().literal( value );
addAssignment( attributePath, valueExpression );
return this; return this;
} }
@ -88,6 +102,9 @@ public class CriteriaUpdateImpl<T> extends AbstractManipulationCriteriaQuery<T>
+ ( (PathImplementor) attributePath ).getPathIdentifier() + "]" + ( (PathImplementor) attributePath ).getPathIdentifier() + "]"
); );
} }
if ( value == null ) {
throw new IllegalArgumentException( "Assignment value expression cannot be null. Did you mean to pass null as a literal?" );
}
assignments.add( new Assignment<Y>( (SingularAttributePath<Y>) attributePath, value ) ); assignments.add( new Assignment<Y>( (SingularAttributePath<Y>) attributePath, value ) );
} }

View File

@ -50,14 +50,7 @@ import org.hibernate.Hibernate;
import org.hibernate.SessionFactory; import org.hibernate.SessionFactory;
import org.hibernate.cache.spi.RegionFactory; import org.hibernate.cache.spi.RegionFactory;
import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.NotYetImplementedException;
import org.hibernate.ejb.AvailableSettings;
import org.hibernate.ejb.HibernateEntityManagerFactory; import org.hibernate.ejb.HibernateEntityManagerFactory;
import org.hibernate.ejb.HibernateQuery;
import org.hibernate.jpa.boot.internal.SettingsImpl;
import org.hibernate.jpa.criteria.CriteriaBuilderImpl;
import org.hibernate.jpa.internal.metamodel.MetamodelImpl;
import org.hibernate.jpa.internal.util.PersistenceUtilHelper;
import org.hibernate.engine.spi.NamedQueryDefinition; import org.hibernate.engine.spi.NamedQueryDefinition;
import org.hibernate.engine.spi.NamedQueryDefinitionBuilder; import org.hibernate.engine.spi.NamedQueryDefinitionBuilder;
import org.hibernate.engine.spi.NamedSQLQueryDefinition; import org.hibernate.engine.spi.NamedSQLQueryDefinition;
@ -67,6 +60,12 @@ import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.UUIDGenerator; import org.hibernate.id.UUIDGenerator;
import org.hibernate.internal.SessionFactoryImpl; import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.jpa.AvailableSettings;
import org.hibernate.jpa.HibernateQuery;
import org.hibernate.jpa.boot.internal.SettingsImpl;
import org.hibernate.jpa.criteria.CriteriaBuilderImpl;
import org.hibernate.jpa.internal.metamodel.MetamodelImpl;
import org.hibernate.jpa.internal.util.PersistenceUtilHelper;
import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.PersistentClass;
import org.hibernate.metadata.ClassMetadata; import org.hibernate.metadata.ClassMetadata;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
@ -205,10 +204,16 @@ public class EntityManagerFactoryImpl implements HibernateEntityManagerFactory {
} }
public EntityManager createEntityManager(Map map) { public EntityManager createEntityManager(Map map) {
return createEntityManager( SynchronizationType.SYNCHRONIZED, map );
}
@Override
public EntityManager createEntityManager(SynchronizationType synchronizationType, Map map) {
//TODO support discardOnClose, persistencecontexttype?, interceptor, //TODO support discardOnClose, persistencecontexttype?, interceptor,
return new EntityManagerImpl( return new EntityManagerImpl(
this, this,
PersistenceContextType.EXTENDED, PersistenceContextType.EXTENDED,
synchronizationType,
transactionType, transactionType,
discardOnClose, discardOnClose,
sessionInterceptorClass, sessionInterceptorClass,
@ -216,12 +221,6 @@ public class EntityManagerFactoryImpl implements HibernateEntityManagerFactory {
); );
} }
@Override
public EntityManager createEntityManager(SynchronizationType synchronizationType, Map map) {
// todo : implement it
throw new NotYetImplementedException( "Not yet implemented" );
}
public CriteriaBuilder getCriteriaBuilder() { public CriteriaBuilder getCriteriaBuilder() {
return criteriaBuilder; return criteriaBuilder;
} }

View File

@ -25,6 +25,7 @@ package org.hibernate.jpa.internal;
import javax.persistence.PersistenceContextType; import javax.persistence.PersistenceContextType;
import javax.persistence.PersistenceException; import javax.persistence.PersistenceException;
import javax.persistence.SynchronizationType;
import javax.persistence.spi.PersistenceUnitTransactionType; import javax.persistence.spi.PersistenceUnitTransactionType;
import java.util.Map; import java.util.Map;
@ -35,10 +36,10 @@ import org.hibernate.Interceptor;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.annotations.common.util.ReflectHelper; import org.hibernate.annotations.common.util.ReflectHelper;
import org.hibernate.ejb.AbstractEntityManagerImpl; import org.hibernate.ejb.AbstractEntityManagerImpl;
import org.hibernate.ejb.AvailableSettings;
import org.hibernate.engine.spi.SessionBuilderImplementor; import org.hibernate.engine.spi.SessionBuilderImplementor;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.SessionOwner; import org.hibernate.engine.spi.SessionOwner;
import org.hibernate.jpa.AvailableSettings;
/** /**
* Hibernate implementation of {@link javax.persistence.EntityManager}. * Hibernate implementation of {@link javax.persistence.EntityManager}.
@ -58,11 +59,12 @@ public class EntityManagerImpl extends AbstractEntityManagerImpl implements Sess
public EntityManagerImpl( public EntityManagerImpl(
EntityManagerFactoryImpl entityManagerFactory, EntityManagerFactoryImpl entityManagerFactory,
PersistenceContextType pcType, PersistenceContextType pcType,
SynchronizationType synchronizationType,
PersistenceUnitTransactionType transactionType, PersistenceUnitTransactionType transactionType,
boolean discardOnClose, boolean discardOnClose,
Class sessionInterceptorClass, Class sessionInterceptorClass,
Map properties) { Map properties) {
super( entityManagerFactory, pcType, transactionType, properties ); super( entityManagerFactory, pcType, synchronizationType, transactionType, properties );
this.open = true; this.open = true;
this.discardOnClose = discardOnClose; this.discardOnClose = discardOnClose;
Object localSessionInterceptor = null; Object localSessionInterceptor = null;
@ -109,10 +111,10 @@ public class EntityManagerImpl extends AbstractEntityManagerImpl implements Sess
sessionBuilder.interceptor( interceptor ); sessionBuilder.interceptor( interceptor );
} }
catch (InstantiationException e) { catch (InstantiationException e) {
throw new PersistenceException("Unable to instanciate session interceptor: " + sessionInterceptorClass, e); throw new PersistenceException("Unable to instantiate session interceptor: " + sessionInterceptorClass, e);
} }
catch (IllegalAccessException e) { catch (IllegalAccessException e) {
throw new PersistenceException("Unable to instanciate session interceptor: " + sessionInterceptorClass, e); throw new PersistenceException("Unable to instantiate session interceptor: " + sessionInterceptorClass, e);
} }
catch (ClassCastException e) { catch (ClassCastException e) {
throw new PersistenceException("Session interceptor does not implement Interceptor: " + sessionInterceptorClass, e); throw new PersistenceException("Session interceptor does not implement Interceptor: " + sessionInterceptorClass, e);

View File

@ -42,6 +42,7 @@ import javax.persistence.PessimisticLockScope;
import javax.persistence.Query; import javax.persistence.Query;
import javax.persistence.QueryTimeoutException; import javax.persistence.QueryTimeoutException;
import javax.persistence.StoredProcedureQuery; import javax.persistence.StoredProcedureQuery;
import javax.persistence.SynchronizationType;
import javax.persistence.TransactionRequiredException; import javax.persistence.TransactionRequiredException;
import javax.persistence.Tuple; import javax.persistence.Tuple;
import javax.persistence.TupleElement; import javax.persistence.TupleElement;
@ -156,6 +157,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
private EntityManagerFactoryImpl entityManagerFactory; private EntityManagerFactoryImpl entityManagerFactory;
protected transient TransactionImpl tx = new TransactionImpl( this ); protected transient TransactionImpl tx = new TransactionImpl( this );
protected PersistenceContextType persistenceContextType; protected PersistenceContextType persistenceContextType;
private SynchronizationType synchronizationType;
private PersistenceUnitTransactionType transactionType; private PersistenceUnitTransactionType transactionType;
private Map<String, Object> properties; private Map<String, Object> properties;
private LockOptions lockOptions; private LockOptions lockOptions;
@ -163,10 +165,12 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
protected AbstractEntityManagerImpl( protected AbstractEntityManagerImpl(
EntityManagerFactoryImpl entityManagerFactory, EntityManagerFactoryImpl entityManagerFactory,
PersistenceContextType type, PersistenceContextType type,
SynchronizationType synchronizationType,
PersistenceUnitTransactionType transactionType, PersistenceUnitTransactionType transactionType,
Map properties) { Map properties) {
this.entityManagerFactory = entityManagerFactory; this.entityManagerFactory = entityManagerFactory;
this.persistenceContextType = type; this.persistenceContextType = type;
this.synchronizationType = synchronizationType;
this.transactionType = transactionType; this.transactionType = transactionType;
this.lockOptions = new LockOptions(); this.lockOptions = new LockOptions();
@ -181,13 +185,29 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
} }
// protected PersistenceUnitTransactionType transactionType() {
// return transactionType;
// }
//
// protected SynchronizationType synchronizationType() {
// return synchronizationType;
// }
//
// public boolean shouldAutoJoinTransactions() {
// // the Session should auto join only if using non-JTA transactions or if the synchronization type
// // was specified as SYNCHRONIZED
// return transactionType != PersistenceUnitTransactionType.JTA
// || synchronizationType == SynchronizationType.SYNCHRONIZED;
// }
public PersistenceUnitTransactionType getTransactionType() { public PersistenceUnitTransactionType getTransactionType() {
return transactionType; return transactionType;
} }
protected void postInit() { protected void postInit() {
//register in Sync if needed //register in Sync if needed
if ( PersistenceUnitTransactionType.JTA.equals( transactionType ) ) { if ( transactionType == PersistenceUnitTransactionType.JTA
&& synchronizationType == SynchronizationType.SYNCHRONIZED ) {
joinTransaction( false ); joinTransaction( false );
} }

View File

@ -0,0 +1,192 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.ejb.test.transaction;
import javax.persistence.EntityManager;
import javax.persistence.LockModeType;
import javax.persistence.SynchronizationType;
import javax.persistence.TransactionRequiredException;
import javax.persistence.criteria.CriteriaDelete;
import javax.persistence.criteria.CriteriaUpdate;
import javax.persistence.criteria.Root;
import java.util.Map;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.ejb.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.transaction.internal.jta.CMTTransaction;
import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
import org.hibernate.jpa.AvailableSettings;
import org.junit.Test;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.jta.TestingJtaBootstrap;
import org.hibernate.testing.jta.TestingJtaPlatformImpl;
import org.hibernate.testing.junit4.ExtraAssertions;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* Tests of the JPA 2.1 added {@link SynchronizationType} handling. {@link SynchronizationType#SYNCHRONIZED} is
* the same as 2.0 behavior, so we do not explicitly test for that ({@link TransactionJoiningTest} handles it).
* Tests here specifically test the {@link SynchronizationType#UNSYNCHRONIZED} behavior
*
* @author Steve Ebersole
*/
@TestForIssue( jiraKey = "HHH-7451" )
public class SynchronizationTypeTest extends BaseEntityManagerFunctionalTestCase {
@Override
protected void addConfigOptions(Map options) {
super.addConfigOptions( options );
TestingJtaBootstrap.prepare( options );
options.put( AvailableSettings.TRANSACTION_TYPE, "JTA" );
}
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] { Book.class };
}
@Test
public void testUnSynchronizedExplicitJoinHandling() throws Exception {
// JPA 2.1 adds this notion allowing to open an EM using a specified "SynchronizationType".
assertFalse( JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) );
EntityManager entityManager = entityManagerFactory().createEntityManager( SynchronizationType.UNSYNCHRONIZED, null );
TransactionJoinHandlingChecker.validateExplicitJoiningHandling( entityManager );
}
@Test
public void testImplicitJoining() throws Exception {
// here the transaction is started before the EM is opened. Because the SynchronizationType is UNSYNCHRONIZED
// though, it should not auto join the transaction
assertFalse( "setup problem", JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) );
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
assertTrue( "setup problem", JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) );
EntityManager entityManager = entityManagerFactory().createEntityManager( SynchronizationType.UNSYNCHRONIZED, null );
SessionImplementor session = entityManager.unwrap( SessionImplementor.class );
Transaction hibernateTransaction = ( (Session) session ).getTransaction();
ExtraAssertions.assertTyping( CMTTransaction.class, hibernateTransaction );
assertFalse( "EM was auto joined on creation", session.getTransactionCoordinator().isSynchronizationRegistered() );
assertFalse( "EM was auto joined on creation", hibernateTransaction.isParticipating() );
session.getFlushMode();
assertFalse( session.getTransactionCoordinator().isSynchronizationRegistered() );
assertFalse( hibernateTransaction.isParticipating() );
entityManager.joinTransaction();
assertTrue( JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) );
assertTrue( hibernateTransaction.isActive() );
assertTrue( session.getTransactionCoordinator().isSynchronizationRegistered() );
assertTrue( hibernateTransaction.isParticipating() );
assertTrue( entityManager.isOpen() );
assertTrue( session.isOpen() );
entityManager.close();
assertFalse( entityManager.isOpen() );
assertTrue( session.isOpen() );
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit();
assertFalse( entityManager.isOpen() );
assertFalse( session.isOpen() );
}
@Test
public void testDisallowedOperations() throws Exception {
// test calling operations that are disallowed while a UNSYNCHRONIZED persistence context is not
// yet joined/enlisted
assertFalse( "setup problem", JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) );
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
assertTrue(
"setup problem", JtaStatusHelper.isActive(
TestingJtaPlatformImpl.INSTANCE
.getTransactionManager()
)
);
EntityManager entityManager = entityManagerFactory().createEntityManager( SynchronizationType.UNSYNCHRONIZED, null );
// explicit flushing
try {
entityManager.flush();
fail( "Expecting flush() call to fail" );
}
catch (TransactionRequiredException expected) {
}
// bulk operations
try {
entityManager.createQuery( "delete Book" ).executeUpdate();
fail( "Expecting executeUpdate() call to fail" );
}
catch (TransactionRequiredException expected) {
}
try {
entityManager.createQuery( "update Book set name = null" ).executeUpdate();
fail( "Expecting executeUpdate() call to fail" );
}
catch (TransactionRequiredException expected) {
}
try {
CriteriaDelete<Book> deleteCriteria = entityManager.getCriteriaBuilder().createCriteriaDelete( Book.class );
deleteCriteria.from( Book.class );
entityManager.createQuery( deleteCriteria ).executeUpdate();
fail( "Expecting executeUpdate() call to fail" );
}
catch (TransactionRequiredException expected) {
}
try {
CriteriaUpdate<Book> updateCriteria = entityManager.getCriteriaBuilder().createCriteriaUpdate( Book.class );
updateCriteria.from( Book.class );
updateCriteria.set( Book_.name, (String) null );
entityManager.createQuery( updateCriteria ).executeUpdate();
fail( "Expecting executeUpdate() call to fail" );
}
catch (TransactionRequiredException expected) {
}
try {
entityManager.createQuery( "select b from Book b" )
.setLockMode( LockModeType.PESSIMISTIC_WRITE )
.getResultList();
fail( "Expecting attempted pessimistic lock query to fail" );
}
catch (TransactionRequiredException expected) {
}
entityManager.close();
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().rollback();
}
}

View File

@ -0,0 +1,85 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.ejb.test.transaction;
import javax.persistence.EntityManager;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.transaction.internal.jta.CMTTransaction;
import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
import org.hibernate.testing.jta.TestingJtaPlatformImpl;
import org.hibernate.testing.junit4.ExtraAssertions;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* Helper for centralized transaction join checking
*
* @author Steve Ebersole
*/
public class TransactionJoinHandlingChecker {
static void validateExplicitJoiningHandling(EntityManager entityManager) throws Exception {
SessionImplementor session = entityManager.unwrap( SessionImplementor.class );
assertFalse( session.getTransactionCoordinator().isSynchronizationRegistered() );
Transaction hibernateTransaction = ((Session) session).getTransaction();
ExtraAssertions.assertTyping( CMTTransaction.class, hibernateTransaction );
assertFalse( hibernateTransaction.isParticipating() );
session.getFlushMode();
assertFalse( session.getTransactionCoordinator().isSynchronizationRegistered() );
assertFalse( hibernateTransaction.isParticipating() );
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
assertTrue( JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) );
assertTrue( hibernateTransaction.isActive() );
assertFalse( hibernateTransaction.isParticipating() );
assertFalse( session.getTransactionCoordinator().isSynchronizationRegistered() );
session.getFlushMode();
assertTrue( JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) );
assertTrue( hibernateTransaction.isActive() );
assertFalse( session.getTransactionCoordinator().isSynchronizationRegistered() );
assertFalse( hibernateTransaction.isParticipating() );
entityManager.joinTransaction();
assertTrue( JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) );
assertTrue( hibernateTransaction.isActive() );
assertTrue( session.getTransactionCoordinator().isSynchronizationRegistered() );
assertTrue( hibernateTransaction.isParticipating() );
assertTrue( entityManager.isOpen() );
assertTrue( session.isOpen() );
entityManager.close();
assertFalse( entityManager.isOpen() );
assertTrue( session.isOpen() );
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit();
assertFalse( entityManager.isOpen() );
assertFalse( session.isOpen() );
}
}

View File

@ -23,19 +23,20 @@
*/ */
package org.hibernate.ejb.test.transaction; package org.hibernate.ejb.test.transaction;
import java.util.Map;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.transaction.Synchronization; import javax.transaction.Synchronization;
import java.util.Map;
import org.junit.Test;
import org.hibernate.Session; import org.hibernate.Session;
import org.hibernate.Transaction; import org.hibernate.Transaction;
import org.hibernate.ejb.AvailableSettings;
import org.hibernate.ejb.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.ejb.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.transaction.internal.jta.CMTTransaction; import org.hibernate.engine.transaction.internal.jta.CMTTransaction;
import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper; import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
import org.hibernate.jpa.AvailableSettings;
import org.junit.Test;
import org.hibernate.testing.jta.TestingJtaBootstrap; import org.hibernate.testing.jta.TestingJtaBootstrap;
import org.hibernate.testing.jta.TestingJtaPlatformImpl; import org.hibernate.testing.jta.TestingJtaPlatformImpl;
@ -60,47 +61,13 @@ public class TransactionJoiningTest extends BaseEntityManagerFunctionalTestCase
assertFalse( JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) ); assertFalse( JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) );
EntityManager entityManager = entityManagerFactory().createEntityManager(); EntityManager entityManager = entityManagerFactory().createEntityManager();
SessionImplementor session = entityManager.unwrap( SessionImplementor.class ); TransactionJoinHandlingChecker.validateExplicitJoiningHandling( entityManager );
assertFalse( session.getTransactionCoordinator().isSynchronizationRegistered() );
Transaction hibernateTransaction = ( (Session) session ).getTransaction();
assertTrue( CMTTransaction.class.isInstance( hibernateTransaction ) );
assertFalse( hibernateTransaction.isParticipating() );
session.getFlushMode();
assertFalse( session.getTransactionCoordinator().isSynchronizationRegistered() );
assertFalse( hibernateTransaction.isParticipating() );
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
assertTrue( JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) );
assertTrue( hibernateTransaction.isActive() );
assertFalse( hibernateTransaction.isParticipating() );
assertFalse( session.getTransactionCoordinator().isSynchronizationRegistered() );
session.getFlushMode();
assertTrue( JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) );
assertTrue( hibernateTransaction.isActive() );
assertFalse( session.getTransactionCoordinator().isSynchronizationRegistered() );
assertFalse( hibernateTransaction.isParticipating() );
entityManager.joinTransaction();
assertTrue( JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) );
assertTrue( hibernateTransaction.isActive() );
assertTrue( session.getTransactionCoordinator().isSynchronizationRegistered() );
assertTrue( hibernateTransaction.isParticipating() );
assertTrue( entityManager.isOpen() );
assertTrue( session.isOpen() );
entityManager.close();
assertFalse( entityManager.isOpen() );
assertTrue( session.isOpen() );
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit();
assertFalse( entityManager.isOpen() );
assertFalse( session.isOpen() );
} }
@Test @Test
public void testImplicitJoining() throws Exception { public void testImplicitJoining() throws Exception {
// here the transaction is started before the EM is opened...
assertFalse( JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) ); assertFalse( JtaStatusHelper.isActive( TestingJtaPlatformImpl.INSTANCE.getTransactionManager() ) );
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().begin();
@ -171,5 +138,4 @@ public class TransactionJoiningTest extends BaseEntityManagerFunctionalTestCase
); );
TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit(); TestingJtaPlatformImpl.INSTANCE.getTransactionManager().commit();
} }
} }