HHH-7451 - Integrate Draft 7 of the JPA 2.1 spec : SynchronizationType
This commit is contained in:
parent
f8d06216e5
commit
6a65c3e7e6
|
@ -218,12 +218,17 @@ public class TransactionCoordinatorImpl implements TransactionCoordinator {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( currentHibernateTransaction.getJoinStatus() != JoinStatus.JOINED ) {
|
||||||
|
// the transaction is not (yet) joined, see if we should join...
|
||||||
if ( ! transactionContext.shouldAutoJoinTransaction() ) {
|
if ( ! transactionContext.shouldAutoJoinTransaction() ) {
|
||||||
|
// 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 ) {
|
if ( currentHibernateTransaction.getJoinStatus() != JoinStatus.MARKED_FOR_JOINED ) {
|
||||||
LOG.debug( "Skipping JTA sync registration due to auto join checking" );
|
LOG.debug( "Skipping JTA sync registration due to auto join checking" );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// IMPL NOTE : At this point the local callback is the "maybe" one. The only time that needs to change is if
|
// IMPL NOTE : At this point the local callback is the "maybe" one. The only time that needs to change is if
|
||||||
// we are able to successfully register the transaction synchronization in which case the local callback would become
|
// we are able to successfully register the transaction synchronization in which case the local callback would become
|
||||||
|
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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() );
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue