* now a transaction is marked for rollback for all RuntimeExceptions not only the CosntraintViolationExcpetion.
* Also updated FlushAndTransactionTest which had invalid assertions.


git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18850 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Hardy Ferentschik 2010-02-22 21:17:12 +00:00
parent b15adba4ef
commit f3aa0c63bb
5 changed files with 213 additions and 124 deletions

View File

@ -63,7 +63,6 @@ import javax.transaction.Status;
import javax.transaction.Synchronization; import javax.transaction.Synchronization;
import javax.transaction.SystemException; import javax.transaction.SystemException;
import javax.transaction.TransactionManager; import javax.transaction.TransactionManager;
import javax.validation.ConstraintViolationException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -112,6 +111,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
private static final Logger log = LoggerFactory.getLogger( AbstractEntityManagerImpl.class ); private static final Logger log = LoggerFactory.getLogger( AbstractEntityManagerImpl.class );
private static final List<String> entityManagerSpecificProperties = new ArrayList<String>(); private static final List<String> entityManagerSpecificProperties = new ArrayList<String>();
static { static {
entityManagerSpecificProperties.add( AvailableSettings.LOCK_SCOPE ); entityManagerSpecificProperties.add( AvailableSettings.LOCK_SCOPE );
entityManagerSpecificProperties.add( AvailableSettings.LOCK_TIMEOUT ); entityManagerSpecificProperties.add( AvailableSettings.LOCK_TIMEOUT );
@ -136,9 +136,9 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
this.persistenceContextType = type; this.persistenceContextType = type;
this.transactionType = transactionType; this.transactionType = transactionType;
this.lockOptions = new LockOptions( ); this.lockOptions = new LockOptions();
this.properties = new HashMap<String, Object>(); this.properties = new HashMap<String, Object>();
if(properties != null) { if ( properties != null ) {
for ( String key : entityManagerSpecificProperties ) { for ( String key : entityManagerSpecificProperties ) {
if ( properties.containsKey( key ) ) { if ( properties.containsKey( key ) ) {
this.properties.put( key, properties.get( key ) ); this.properties.put( key, properties.get( key ) );
@ -159,7 +159,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
private void applyProperties() { private void applyProperties() {
getSession().setFlushMode( ConfigurationHelper.getFlushMode( properties.get( AvailableSettings.FLUSH_MODE ) ) ); getSession().setFlushMode( ConfigurationHelper.getFlushMode( properties.get( AvailableSettings.FLUSH_MODE ) ) );
setLockOptions(this.properties, this.lockOptions); setLockOptions( this.properties, this.lockOptions );
getSession().setCacheMode( getSession().setCacheMode(
CacheModeHelper.interpretCacheMode( CacheModeHelper.interpretCacheMode(
currentCacheStoreMode(), currentCacheStoreMode(),
@ -172,16 +172,16 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
return determineCacheRetrieveMode( properties ); return determineCacheRetrieveMode( properties );
} }
private CacheRetrieveMode determineCacheRetrieveMode(Map<String,Object> settings) { private CacheRetrieveMode determineCacheRetrieveMode(Map<String, Object> settings) {
return (CacheRetrieveMode) settings.get( AvailableSettings.SHARED_CACHE_RETRIEVE_MODE ); return ( CacheRetrieveMode ) settings.get( AvailableSettings.SHARED_CACHE_RETRIEVE_MODE );
} }
private CacheStoreMode currentCacheStoreMode() { private CacheStoreMode currentCacheStoreMode() {
return determineCacheStoreMode( properties ); return determineCacheStoreMode( properties );
} }
private CacheStoreMode determineCacheStoreMode(Map<String,Object> settings) { private CacheStoreMode determineCacheStoreMode(Map<String, Object> settings) {
return (CacheStoreMode) properties.get( AvailableSettings.SHARED_CACHE_STORE_MODE ); return ( CacheStoreMode ) properties.get( AvailableSettings.SHARED_CACHE_STORE_MODE );
} }
private void setLockOptions(Map<String, Object> props, LockOptions options) { private void setLockOptions(Map<String, Object> props, LockOptions options) {
@ -229,19 +229,19 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
* set. * set.
*/ */
private void setDefaultProperties() { private void setDefaultProperties() {
if ( properties.get( AvailableSettings.FLUSH_MODE ) == null) { if ( properties.get( AvailableSettings.FLUSH_MODE ) == null ) {
properties.put( AvailableSettings.FLUSH_MODE, getSession().getFlushMode().toString() ); properties.put( AvailableSettings.FLUSH_MODE, getSession().getFlushMode().toString() );
} }
if ( properties.get( AvailableSettings.LOCK_SCOPE ) == null) { if ( properties.get( AvailableSettings.LOCK_SCOPE ) == null ) {
this.properties.put( AvailableSettings.LOCK_SCOPE, PessimisticLockScope.EXTENDED.name() ); this.properties.put( AvailableSettings.LOCK_SCOPE, PessimisticLockScope.EXTENDED.name() );
} }
if ( properties.get( AvailableSettings.LOCK_TIMEOUT ) == null) { if ( properties.get( AvailableSettings.LOCK_TIMEOUT ) == null ) {
properties.put( AvailableSettings.LOCK_TIMEOUT, LockOptions.WAIT_FOREVER ); properties.put( AvailableSettings.LOCK_TIMEOUT, LockOptions.WAIT_FOREVER );
} }
if ( properties.get( AvailableSettings.SHARED_CACHE_RETRIEVE_MODE ) == null) { if ( properties.get( AvailableSettings.SHARED_CACHE_RETRIEVE_MODE ) == null ) {
properties.put( AvailableSettings.SHARED_CACHE_RETRIEVE_MODE, CacheModeHelper.DEFAULT_RETRIEVE_MODE ); properties.put( AvailableSettings.SHARED_CACHE_RETRIEVE_MODE, CacheModeHelper.DEFAULT_RETRIEVE_MODE );
} }
if ( properties.get( AvailableSettings.SHARED_CACHE_STORE_MODE ) == null) { if ( properties.get( AvailableSettings.SHARED_CACHE_STORE_MODE ) == null ) {
properties.put( AvailableSettings.SHARED_CACHE_STORE_MODE, CacheModeHelper.DEFAULT_STORE_MODE ); properties.put( AvailableSettings.SHARED_CACHE_STORE_MODE, CacheModeHelper.DEFAULT_STORE_MODE );
} }
} }
@ -261,7 +261,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
if ( hqlQuery.getReturnTypes().length != 1 ) { if ( hqlQuery.getReturnTypes().length != 1 ) {
throw new IllegalArgumentException( "Cannot create TypedQuery for query with more than one return" ); throw new IllegalArgumentException( "Cannot create TypedQuery for query with more than one return" );
} }
if ( ! resultClass.isAssignableFrom( hqlQuery.getReturnTypes()[0].getReturnedClass() ) ) { if ( !resultClass.isAssignableFrom( hqlQuery.getReturnTypes()[0].getReturnedClass() ) ) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Type specified for TypedQuery [" + "Type specified for TypedQuery [" +
resultClass.getName() + resultClass.getName() +
@ -290,7 +290,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
// determine if we need a result transformer // determine if we need a result transformer
List tupleElements = Tuple.class.equals( resultClass ) List tupleElements = Tuple.class.equals( resultClass )
? ( (CompoundSelectionImpl<Tuple>) selection ).getCompoundSelectionItems() ? ( ( CompoundSelectionImpl<Tuple> ) selection ).getCompoundSelectionItems()
: null; : null;
if ( options.getValueHandlers() != null || tupleElements != null ) { if ( options.getValueHandlers() != null || tupleElements != null ) {
hqlQuery.setResultTransformer( hqlQuery.setResultTransformer(
@ -321,7 +321,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
valueHandlerResult = tuple; valueHandlerResult = tuple;
} }
else { else {
valueHandlerResult = new Object[ tuple.length ]; valueHandlerResult = new Object[tuple.length];
for ( int i = 0; i < tuple.length; i++ ) { for ( int i = 0; i < tuple.length; i++ ) {
ValueHandlerFactory.ValueHandler valueHandler = valueHandlers.get( i ); ValueHandlerFactory.ValueHandler valueHandler = valueHandlers.get( i );
valueHandlerResult[i] = valueHandler == null valueHandlerResult[i] = valueHandler == null
@ -352,10 +352,12 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
public <X> X get(TupleElement<X> tupleElement) { public <X> X get(TupleElement<X> tupleElement) {
int index = tupleElements.indexOf( tupleElement ); int index = tupleElements.indexOf( tupleElement );
if ( index < 0 ) { if ( index < 0 ) {
throw new IllegalArgumentException( "Requested tuple element did not correspond to element in the result tuple" ); throw new IllegalArgumentException(
"Requested tuple element did not correspond to element in the result tuple"
);
} }
// index should be "in range" by nature of size check in ctor // index should be "in range" by nature of size check in ctor
return (X) tuples[index]; return ( X ) tuples[index];
} }
public Object get(String alias) { public Object get(String alias) {
@ -364,7 +366,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
alias = alias.trim(); alias = alias.trim();
if ( alias.length() > 0 ) { if ( alias.length() > 0 ) {
int i = 0; int i = 0;
for ( TupleElement selection : (List<TupleElement>) tupleElements ) { for ( TupleElement selection : ( List<TupleElement> ) tupleElements ) {
if ( alias.equals( selection.getAlias() ) ) { if ( alias.equals( selection.getAlias() ) ) {
index = i; index = i;
break; break;
@ -383,7 +385,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
public <X> X get(String alias, Class<X> type) { public <X> X get(String alias, Class<X> type) {
return (X) get( alias ); return ( X ) get( alias );
} }
public Object get(int i) { public Object get(int i) {
@ -396,7 +398,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
public <X> X get(int i, Class<X> type) { public <X> X get(int i, Class<X> type) {
return (X) get( i ); return ( X ) get( i );
} }
public Object[] toArray() { public Object[] toArray() {
@ -404,7 +406,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
public List<TupleElement<?>> getElements() { public List<TupleElement<?>> getElements() {
return (List<TupleElement<?>>) tupleElements; return ( List<TupleElement<?>> ) tupleElements;
} }
} }
} }
@ -440,7 +442,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
if ( namedQuery.getReturnTypes().length != 1 ) { if ( namedQuery.getReturnTypes().length != 1 ) {
throw new IllegalArgumentException( "Cannot create TypedQuery for query with more than one return" ); throw new IllegalArgumentException( "Cannot create TypedQuery for query with more than one return" );
} }
if ( ! resultClass.isAssignableFrom( namedQuery.getReturnTypes()[0].getReturnedClass() ) ) { if ( !resultClass.isAssignableFrom( namedQuery.getReturnTypes()[0].getReturnedClass() ) ) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Type specified for TypedQuery [" + "Type specified for TypedQuery [" +
resultClass.getName() + resultClass.getName() +
@ -512,19 +514,19 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <A> A find(Class<A> entityClass, Object primaryKey) { public <A> A find(Class<A> entityClass, Object primaryKey) {
return find( entityClass, primaryKey, null, null); return find( entityClass, primaryKey, null, null );
} }
public <T> T find(Class<T> entityClass, Object primaryKey, Map<String, Object> properties) { public <T> T find(Class<T> entityClass, Object primaryKey, Map<String, Object> properties) {
return find(entityClass, primaryKey, null, null); return find( entityClass, primaryKey, null, null );
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <A> A find(Class<A> entityClass, Object primaryKey, LockModeType lockModeType) { public <A> A find(Class<A> entityClass, Object primaryKey, LockModeType lockModeType) {
return find(entityClass, primaryKey, lockModeType, null); return find( entityClass, primaryKey, lockModeType, null );
} }
public <A> A find(Class<A> entityClass, Object primaryKey, LockModeType lockModeType, Map<String, Object> properties) { public <A> A find(Class<A> entityClass, Object primaryKey, LockModeType lockModeType, Map<String, Object> properties) {
CacheMode previousCacheMode = getSession().getCacheMode(); CacheMode previousCacheMode = getSession().getCacheMode();
CacheMode cacheMode = determineAppropriateLocalCacheMode( properties ); CacheMode cacheMode = determineAppropriateLocalCacheMode( properties );
LockOptions lockOptions = null; LockOptions lockOptions = null;
@ -536,8 +538,9 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
getLockRequest( lockModeType, properties ) getLockRequest( lockModeType, properties )
); );
} }
else else {
return ( A ) getSession().get( entityClass, ( Serializable ) primaryKey ); return ( A ) getSession().get( entityClass, ( Serializable ) primaryKey );
}
} }
catch ( ObjectDeletedException e ) { catch ( ObjectDeletedException e ) {
//the spec is silent about people doing remove() find() on the same PC //the spec is silent about people doing remove() find() on the same PC
@ -557,7 +560,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
throw new IllegalArgumentException( e.getMessage(), e ); throw new IllegalArgumentException( e.getMessage(), e );
} }
catch ( HibernateException he ) { catch ( HibernateException he ) {
throw convert( he , lockOptions ); throw convert( he, lockOptions );
} }
finally { finally {
getSession().setCacheMode( previousCacheMode ); getSession().setCacheMode( previousCacheMode );
@ -635,15 +638,15 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
public void refresh(Object entity) { public void refresh(Object entity) {
refresh(entity, null, null); refresh( entity, null, null );
} }
public void refresh(Object entity, Map<String, Object> properties) { public void refresh(Object entity, Map<String, Object> properties) {
refresh(entity, null, null); refresh( entity, null, null );
} }
public void refresh(Object entity, LockModeType lockModeType) { public void refresh(Object entity, LockModeType lockModeType) {
refresh(entity, lockModeType, null); refresh( entity, lockModeType, null );
} }
public void refresh(Object entity, LockModeType lockModeType, Map<String, Object> properties) { public void refresh(Object entity, LockModeType lockModeType, Map<String, Object> properties) {
@ -656,16 +659,18 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
if ( !getSession().contains( entity ) ) { if ( !getSession().contains( entity ) ) {
throw new IllegalArgumentException( "Entity not managed" ); throw new IllegalArgumentException( "Entity not managed" );
} }
if(lockModeType != null) if ( lockModeType != null ) {
getSession().refresh( entity, (lockOptions = getLockRequest(lockModeType, properties) ) ); getSession().refresh( entity, ( lockOptions = getLockRequest( lockModeType, properties ) ) );
else }
else {
getSession().refresh( entity ); getSession().refresh( entity );
}
} }
catch ( MappingException e ) { catch ( MappingException e ) {
throw new IllegalArgumentException( e.getMessage(), e ); throw new IllegalArgumentException( e.getMessage(), e );
} }
catch ( HibernateException he ) { catch ( HibernateException he ) {
throw convert( he, lockOptions); throw convert( he, lockOptions );
} }
finally { finally {
getSession().setCacheMode( previousCacheMode ); getSession().setCacheMode( previousCacheMode );
@ -693,7 +698,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
if ( !contains( entity ) ) { if ( !contains( entity ) ) {
throw new IllegalArgumentException( "entity not in the persistence context" ); throw new IllegalArgumentException( "entity not in the persistence context" );
} }
return getLockModeType(getSession().getCurrentLockMode(entity)); return getLockModeType( getSession().getCurrentLockMode( entity ) );
} }
public void setProperty(String s, Object o) { public void setProperty(String s, Object o) {
@ -822,7 +827,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
public void lock(Object entity, LockModeType lockMode) { public void lock(Object entity, LockModeType lockMode) {
lock( entity, lockMode, null); lock( entity, lockMode, null );
} }
public void lock(Object entity, LockModeType lockModeType, Map<String, Object> properties) { public void lock(Object entity, LockModeType lockModeType, Map<String, Object> properties) {
@ -834,10 +839,11 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
if ( !contains( entity ) ) { if ( !contains( entity ) ) {
throw new IllegalArgumentException( "entity not in the persistence context" ); throw new IllegalArgumentException( "entity not in the persistence context" );
} }
getSession().buildLockRequest( (lockOptions = getLockRequest(lockModeType, properties))).lock( entity ); getSession().buildLockRequest( ( lockOptions = getLockRequest( lockModeType, properties ) ) )
.lock( entity );
} }
catch ( HibernateException he ) { catch ( HibernateException he ) {
throw convert( he , lockOptions); throw convert( he, lockOptions );
} }
} }
@ -903,9 +909,9 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
return ( T ) getSession(); return ( T ) getSession();
} }
if ( EntityManager.class.isAssignableFrom( clazz ) ) { if ( EntityManager.class.isAssignableFrom( clazz ) ) {
return (T) this; return ( T ) this;
} }
throw new PersistenceException( "Hibernate cannot unwrap " + clazz); throw new PersistenceException( "Hibernate cannot unwrap " + clazz );
} }
private void joinTransaction(boolean ignoreNotJoining) { private void joinTransaction(boolean ignoreNotJoining) {
@ -989,7 +995,7 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
catch ( HibernateException he ) { catch ( HibernateException he ) {
throw convert( he ); throw convert( he );
} }
catch( PersistenceException pe ) { catch ( PersistenceException pe ) {
handlePersistenceException( pe ); handlePersistenceException( pe );
throw pe; throw pe;
} }
@ -1091,21 +1097,17 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
*/ */
//FIXME should we remove all calls to this method and use convert(RuntimeException) ? //FIXME should we remove all calls to this method and use convert(RuntimeException) ?
public RuntimeException convert(HibernateException e) { public RuntimeException convert(HibernateException e) {
return convert(e, null); return convert( e, null );
} }
/**
* {@inheritDoc}
*/
public RuntimeException convert(RuntimeException e) { public RuntimeException convert(RuntimeException e) {
RuntimeException result = e; RuntimeException result = e;
if ( e instanceof HibernateException ) { if ( e instanceof HibernateException ) {
result = convert( (HibernateException) e ); result = convert( ( HibernateException ) e );
} }
else if (e instanceof ConstraintViolationException) { else {
markAsRollback(); markAsRollback();
} }
//if any RT exception should mark the tx for rollback, convert the last else if into a else
return result; return result;
} }
@ -1119,12 +1121,12 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
return converted; return converted;
} }
else if ( e instanceof org.hibernate.OptimisticLockException ) { else if ( e instanceof org.hibernate.OptimisticLockException ) {
PersistenceException converted = wrapLockException(e, lockOptions); PersistenceException converted = wrapLockException( e, lockOptions );
handlePersistenceException( converted ); handlePersistenceException( converted );
return converted; return converted;
} }
else if ( e instanceof org.hibernate.PessimisticLockException ) { else if ( e instanceof org.hibernate.PessimisticLockException ) {
PersistenceException converted = wrapLockException(e, lockOptions); PersistenceException converted = wrapLockException( e, lockOptions );
handlePersistenceException( converted ); handlePersistenceException( converted );
return converted; return converted;
} }
@ -1206,17 +1208,17 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
public PersistenceException wrapLockException(HibernateException e, LockOptions lockOptions) { public PersistenceException wrapLockException(HibernateException e, LockOptions lockOptions) {
PersistenceException pe; PersistenceException pe;
if ( e instanceof org.hibernate.OptimisticLockException ) { if ( e instanceof org.hibernate.OptimisticLockException ) {
org.hibernate.OptimisticLockException ole = (org.hibernate.OptimisticLockException)e; org.hibernate.OptimisticLockException ole = ( org.hibernate.OptimisticLockException ) e;
pe = new OptimisticLockException(ole.getMessage(), ole, ole.getEntity()); pe = new OptimisticLockException( ole.getMessage(), ole, ole.getEntity() );
} }
else if ( e instanceof org.hibernate.PessimisticLockException ) { else if ( e instanceof org.hibernate.PessimisticLockException ) {
org.hibernate.PessimisticLockException ple = (org.hibernate.PessimisticLockException)e; org.hibernate.PessimisticLockException ple = ( org.hibernate.PessimisticLockException ) e;
if (lockOptions !=null && lockOptions.getTimeOut() > -1) { if ( lockOptions != null && lockOptions.getTimeOut() > -1 ) {
// assume lock timeout occurred if a timeout or NO WAIT was specified // assume lock timeout occurred if a timeout or NO WAIT was specified
pe = new LockTimeoutException(ple.getMessage(), ple, ple.getEntity()); pe = new LockTimeoutException( ple.getMessage(), ple, ple.getEntity() );
} }
else { else {
pe = new PessimisticLockException(ple.getMessage(), ple, ple.getEntity()); pe = new PessimisticLockException( ple.getMessage(), ple, ple.getEntity() );
} }
} }
else { else {
@ -1224,5 +1226,4 @@ public abstract class AbstractEntityManagerImpl implements HibernateEntityManage
} }
return pe; return pe;
} }
} }

View File

@ -23,21 +23,19 @@
*/ */
package org.hibernate.ejb; package org.hibernate.ejb;
import javax.persistence.PersistenceException; import java.util.List;
import java.util.Map;
import javax.persistence.LockModeType; import javax.persistence.LockModeType;
import javax.persistence.PersistenceException;
import javax.persistence.TypedQuery; import javax.persistence.TypedQuery;
import javax.persistence.criteria.Selection; import javax.persistence.criteria.Selection;
import org.hibernate.CacheMode;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.StaleStateException;
import org.hibernate.LockOptions; import org.hibernate.LockOptions;
import org.hibernate.StaleStateException;
import org.hibernate.ejb.criteria.ValueHandlerFactory; import org.hibernate.ejb.criteria.ValueHandlerFactory;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import java.util.List;
import java.util.Map;
/** /**
* Additional internal contracts for the Hibernate {@link javax.persistence.EntityManager} implementation. * Additional internal contracts for the Hibernate {@link javax.persistence.EntityManager} implementation.
* *
@ -82,6 +80,7 @@ public interface HibernateEntityManagerImplementor extends HibernateEntityManage
* *
* @param e The Hibernate excepton. * @param e The Hibernate excepton.
* @param lockOptions The lock options in effect at the time of exception (can be null) * @param lockOptions The lock options in effect at the time of exception (can be null)
*
* @return The JPA-specified exception * @return The JPA-specified exception
*/ */
public RuntimeException convert(HibernateException e, LockOptions lockOptions); public RuntimeException convert(HibernateException e, LockOptions lockOptions);
@ -93,6 +92,7 @@ public interface HibernateEntityManagerImplementor extends HibernateEntityManage
* Any appropriate/needed calls to {@link #handlePersistenceException} are also made. * Any appropriate/needed calls to {@link #handlePersistenceException} are also made.
* *
* @param e The Hibernate excepton. * @param e The Hibernate excepton.
*
* @return The JPA-specified exception * @return The JPA-specified exception
*/ */
public RuntimeException convert(HibernateException e); public RuntimeException convert(HibernateException e);
@ -111,6 +111,7 @@ public interface HibernateEntityManagerImplementor extends HibernateEntityManage
* *
* @param lockModeType is the requested lock type * @param lockModeType is the requested lock type
* @param properties are the lock properties * @param properties are the lock properties
*
* @return the LockOptions * @return the LockOptions
*/ */
public LockOptions getLockRequest(LockModeType lockModeType, Map<String, Object> properties); public LockOptions getLockRequest(LockModeType lockModeType, Map<String, Object> properties);
@ -133,7 +134,7 @@ public interface HibernateEntityManagerImplementor extends HibernateEntityManage
* *
* @return The * @return The
*/ */
public Map<String,Class> getNamedParameterExplicitTypes(); public Map<String, Class> getNamedParameterExplicitTypes();
public ResultMetadataValidator getResultMetadataValidator(); public ResultMetadataValidator getResultMetadataValidator();
} }
@ -146,6 +147,7 @@ public interface HibernateEntityManagerImplementor extends HibernateEntityManage
* @param selection The selection(s) * @param selection The selection(s)
* @param options The options to use to build the query. * @param options The options to use to build the query.
* @param <T> The query type * @param <T> The query type
*
* @return The typed query * @return The typed query
*/ */
public <T> TypedQuery<T> createQuery(String jpaqlString, Class<T> resultClass, Selection selection, Options options); public <T> TypedQuery<T> createQuery(String jpaqlString, Class<T> resultClass, Selection selection, Options options);

View File

@ -2,17 +2,17 @@
package org.hibernate.ejb.test.exception; package org.hibernate.ejb.test.exception;
import java.util.Map; import java.util.Map;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.EntityNotFoundException; import javax.persistence.EntityNotFoundException;
import javax.persistence.OptimisticLockException; import javax.persistence.OptimisticLockException;
import javax.persistence.PersistenceException; import javax.persistence.PersistenceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.cfg.Environment; import org.hibernate.cfg.Environment;
import org.hibernate.ejb.test.TestCase; import org.hibernate.ejb.test.TestCase;
import org.hibernate.exception.ConstraintViolationException; import org.hibernate.exception.ConstraintViolationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* @author Emmanuel Bernard * @author Emmanuel Bernard
@ -20,7 +20,7 @@ import org.slf4j.LoggerFactory;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public class ExceptionTest extends TestCase { public class ExceptionTest extends TestCase {
private final Logger log = LoggerFactory.getLogger(ExceptionTest.class); private final Logger log = LoggerFactory.getLogger( ExceptionTest.class );
public void testOptimisticLockingException() throws Exception { public void testOptimisticLockingException() throws Exception {
EntityManager em = getOrCreateEntityManager(); EntityManager em = getOrCreateEntityManager();
@ -36,10 +36,12 @@ public class ExceptionTest extends TestCase {
Music music2 = em2.find( Music.class, music.getId() ); Music music2 = em2.find( Music.class, music.getId() );
music2.setName( "HouseMusic" ); music2.setName( "HouseMusic" );
em2.getTransaction().commit(); em2.getTransaction().commit();
} catch (Exception e){ }
catch ( Exception e ) {
em2.getTransaction().rollback(); em2.getTransaction().rollback();
throw e; throw e;
} finally { }
finally {
em2.close(); em2.close();
} }
@ -48,14 +50,14 @@ public class ExceptionTest extends TestCase {
try { try {
em.flush(); em.flush();
fail("Should raise an optimistic lock exception"); fail( "Should raise an optimistic lock exception" );
} }
catch( OptimisticLockException e) { catch ( OptimisticLockException e ) {
//success //success
assertEquals( music, e.getEntity() ); assertEquals( music, e.getEntity() );
} }
catch( Exception e ) { catch ( Exception e ) {
fail("Should raise an optimistic lock exception"); fail( "Should raise an optimistic lock exception" );
} }
finally { finally {
em.getTransaction().rollback(); em.getTransaction().rollback();
@ -64,14 +66,14 @@ public class ExceptionTest extends TestCase {
} }
public void testEntityNotFoundException() throws Exception { public void testEntityNotFoundException() throws Exception {
EntityManager em = getOrCreateEntityManager( ); EntityManager em = getOrCreateEntityManager();
Music music = em.getReference( Music.class, new Integer(-1) ); Music music = em.getReference( Music.class, -1 );
try { try {
music.getName(); music.getName();
fail("Non existent entity should raise an exception when state is accessed"); fail( "Non existent entity should raise an exception when state is accessed" );
} }
catch( EntityNotFoundException e ) { catch ( EntityNotFoundException e ) {
log.debug("success"); log.debug( "success" );
} }
finally { finally {
em.close(); em.close();
@ -79,15 +81,15 @@ public class ExceptionTest extends TestCase {
} }
public void testConstraintViolationException() throws Exception { public void testConstraintViolationException() throws Exception {
EntityManager em = getOrCreateEntityManager( ); EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin(); em.getTransaction().begin();
Music music = new Music(); Music music = new Music();
music.setName( "Jazz" ); music.setName( "Jazz" );
em.persist( music ); em.persist( music );
Musician lui = new Musician(); Musician lui = new Musician();
lui.setName("Lui Armstrong"); lui.setName( "Lui Armstrong" );
lui.setFavouriteMusic(music); lui.setFavouriteMusic( music );
em.persist(lui); em.persist( lui );
em.getTransaction().commit(); em.getTransaction().commit();
try { try {
em.getTransaction().begin(); em.getTransaction().begin();
@ -96,9 +98,9 @@ public class ExceptionTest extends TestCase {
em.getTransaction().commit(); em.getTransaction().commit();
fail(); fail();
} }
catch( PersistenceException e ) { catch ( PersistenceException e ) {
Throwable t = e.getCause(); Throwable t = e.getCause();
assertTrue("Should be a constraint violation", t instanceof ConstraintViolationException); assertTrue( "Should be a constraint violation", t instanceof ConstraintViolationException );
em.getTransaction().rollback(); em.getTransaction().rollback();
} }
finally { finally {
@ -106,16 +108,32 @@ public class ExceptionTest extends TestCase {
} }
} }
// HHH-4676
public void testInterceptor() throws Exception {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
Instrument instrument = new Instrument();
instrument.setName( "Guitar" );
try {
em.persist( instrument );
fail( "Commit should have failed." );
}
catch ( RuntimeException e ) {
assertTrue( em.getTransaction().getRollbackOnly() );
}
em.close();
}
@Override @Override
public Map getConfig() { public Map getConfig() {
Map config = super.getConfig(); Map config = super.getConfig();
config.put( Environment.BATCH_VERSIONED_DATA, "false"); config.put( Environment.BATCH_VERSIONED_DATA, "false" );
return config; return config;
} }
public Class[] getAnnotatedClasses() { public Class[] getAnnotatedClasses() {
return new Class[] { return new Class[] {
Music.class, Musician.class Music.class, Musician.class, Instrument.class
}; };
} }
} }

View File

@ -0,0 +1,74 @@
// $Id:$
/*
* JBoss, Home of Professional Open Source
* Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.hibernate.ejb.test.exception;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.PrePersist;
/**
* @author Hardy Ferentschik
*/
@Entity
public class Instrument {
@Id
@GeneratedValue
private int id;
private String name;
private Type type;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
}
@PrePersist
public void prePersist() {
throw new RuntimeException( "Instrument broken." );
}
public enum Type {
WIND, STRINGS, PERCUSSION
}
}

View File

@ -4,15 +4,15 @@ package org.hibernate.ejb.test.transaction;
import java.util.List; import java.util.List;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.LockModeType; import javax.persistence.LockModeType;
import javax.persistence.OptimisticLockException;
import javax.persistence.PersistenceException;
import javax.persistence.RollbackException; import javax.persistence.RollbackException;
import javax.persistence.TransactionRequiredException; import javax.persistence.TransactionRequiredException;
import javax.persistence.PersistenceException;
import javax.persistence.OptimisticLockException;
import org.hibernate.Session;
import org.hibernate.ejb.HibernateEntityManagerFactory; import org.hibernate.ejb.HibernateEntityManagerFactory;
import org.hibernate.ejb.test.TestCase; import org.hibernate.ejb.test.TestCase;
import org.hibernate.stat.Statistics; import org.hibernate.stat.Statistics;
import org.hibernate.Session;
/** /**
* @author Emmanuel Bernard * @author Emmanuel Bernard
@ -29,14 +29,14 @@ public class FlushAndTransactionTest extends TestCase {
em.flush(); em.flush();
fail( "flush has to be inside a Tx" ); fail( "flush has to be inside a Tx" );
} }
catch (TransactionRequiredException e) { catch ( TransactionRequiredException e ) {
//success //success
} }
try { try {
em.lock( book, LockModeType.READ ); em.lock( book, LockModeType.READ );
fail( "lock has to be inside a Tx" ); fail( "lock has to be inside a Tx" );
} }
catch (TransactionRequiredException e) { catch ( TransactionRequiredException e ) {
//success //success
} }
em.getTransaction().begin(); em.getTransaction().begin();
@ -77,7 +77,7 @@ public class FlushAndTransactionTest extends TestCase {
Book book = new Book(); Book book = new Book();
book.name = "Le petit prince"; book.name = "Le petit prince";
EntityManager em = getOrCreateEntityManager(); EntityManager em = getOrCreateEntityManager();
Statistics stats = ( (HibernateEntityManagerFactory) factory ).getSessionFactory().getStatistics(); Statistics stats = ( ( HibernateEntityManagerFactory ) factory ).getSessionFactory().getStatistics();
stats.clear(); stats.clear();
stats.setStatisticsEnabled( true ); stats.setStatisticsEnabled( true );
@ -120,7 +120,7 @@ public class FlushAndTransactionTest extends TestCase {
Book book = new Book(); Book book = new Book();
book.name = "Le petit prince"; book.name = "Le petit prince";
EntityManager em = getOrCreateEntityManager(); EntityManager em = getOrCreateEntityManager();
Statistics stats = ( (HibernateEntityManagerFactory) factory ).getSessionFactory().getStatistics(); Statistics stats = ( ( HibernateEntityManagerFactory ) factory ).getSessionFactory().getStatistics();
em.getTransaction().begin(); em.getTransaction().begin();
em.persist( book ); em.persist( book );
@ -164,26 +164,17 @@ public class FlushAndTransactionTest extends TestCase {
em.getTransaction().begin(); em.getTransaction().begin();
Book book = new Book(); Book book = new Book();
book.name = "Java for Dummies"; book.name = "Java for Dummies";
em.persist( book );
em.close(); em.close();
book.name = "C# for Dummies";
assertFalse( em.isOpen() ); assertFalse( em.isOpen() );
try { try {
em.flush(); em.flush();
fail( "direct action on a closed em should fail" ); fail( "direct action on a closed em should fail" );
} }
catch (IllegalStateException e) { catch ( IllegalStateException e ) {
//success //success
em.getTransaction().rollback();
} }
em.getTransaction().commit();
assertFalse( em.isOpen() );
em = getOrCreateEntityManager();
em.getTransaction().begin();
book = em.find( Book.class, book.id );
assertEquals( "C# for Dummies", book.name );
em.remove( book );
em.getTransaction().commit();
em.close();
} }
public void testTransactionCommitDoesNotFlush() throws Exception { public void testTransactionCommitDoesNotFlush() throws Exception {
@ -196,7 +187,7 @@ public class FlushAndTransactionTest extends TestCase {
em.close(); em.close();
em = getOrCreateEntityManager(); em = getOrCreateEntityManager();
em.getTransaction().begin(); em.getTransaction().begin();
List result = em.createQuery("select book from Book book where book.name = :title"). List result = em.createQuery( "select book from Book book where book.name = :title" ).
setParameter( "title", book.name ).getResultList(); setParameter( "title", book.name ).getResultList();
assertEquals( "EntityManager.commit() should trigger a flush()", 1, result.size() ); assertEquals( "EntityManager.commit() should trigger a flush()", 1, result.size() );
em.getTransaction().commit(); em.getTransaction().commit();
@ -213,7 +204,7 @@ public class FlushAndTransactionTest extends TestCase {
em.close(); em.close();
em = getOrCreateEntityManager(); em = getOrCreateEntityManager();
em.getTransaction().begin(); em.getTransaction().begin();
List result = em.createQuery("select book from Book book where book.name = :title"). List result = em.createQuery( "select book from Book book where book.name = :title" ).
setParameter( "title", book.name ).getResultList(); setParameter( "title", book.name ).getResultList();
assertEquals( "EntityManager.commit() should trigger a flush()", 1, result.size() ); assertEquals( "EntityManager.commit() should trigger a flush()", 1, result.size() );
assertTrue( em.contains( result.get( 0 ) ) ); assertTrue( em.contains( result.get( 0 ) ) );
@ -232,23 +223,23 @@ public class FlushAndTransactionTest extends TestCase {
em.persist( book ); em.persist( book );
em.flush(); em.flush();
em.clear(); em.clear();
book.setName( "kitty kid"); book.setName( "kitty kid" );
em.merge( book ); em.merge( book );
em.flush(); em.flush();
em.clear(); em.clear();
book.setName( "kitty kid2"); //non updated version book.setName( "kitty kid2" ); //non updated version
em.merge( book ); em.merge( book );
em.flush(); em.flush();
fail( "optimistic locking exception" ); fail( "optimistic locking exception" );
} }
catch (PersistenceException e) { catch ( PersistenceException e ) {
//success //success
} }
try { try {
em.getTransaction().commit(); em.getTransaction().commit();
fail( "Commit should be rollbacked" ); fail( "Commit should be rollbacked" );
} }
catch (RollbackException e) { catch ( RollbackException e ) {
//success //success
} }
finally { finally {
@ -266,18 +257,21 @@ public class FlushAndTransactionTest extends TestCase {
em.persist( book ); em.persist( book );
em.flush(); em.flush();
em.clear(); em.clear();
book.setName( "kitty kid"); book.setName( "kitty kid" );
em.merge( book ); em.merge( book );
em.flush(); em.flush();
em.clear(); em.clear();
book.setName( "kitty kid2"); //non updated version book.setName( "kitty kid2" ); //non updated version
em.unwrap( Session.class ).update( book ); em.unwrap( Session.class ).update( book );
try { try {
em.getTransaction().commit(); em.getTransaction().commit();
fail( "Commit should be rollbacked" ); fail( "Commit should be rollbacked" );
} }
catch (RollbackException e) { catch ( RollbackException e ) {
assertTrue( "During flush a StateStateException is wrapped into a OptimisticLockException", e.getCause() instanceof OptimisticLockException ); assertTrue(
"During flush a StateStateException is wrapped into a OptimisticLockException",
e.getCause() instanceof OptimisticLockException
);
} }
finally { finally {
em.close(); em.close();
@ -301,7 +295,7 @@ public class FlushAndTransactionTest extends TestCase {
} }
public Class[] getAnnotatedClasses() { public Class[] getAnnotatedClasses() {
return new Class[]{ return new Class[] {
Book.class Book.class
}; };
} }