HHH-7138 - Hibernate implements JPA @OneToMany collection versioning incorrectly

This commit is contained in:
Steve Ebersole 2012-03-05 16:27:52 -06:00
parent 94e79944b8
commit 05c3679373
3 changed files with 59 additions and 27 deletions

View File

@ -436,8 +436,15 @@ public abstract class CollectionBinder {
}
collection.setMutable( !property.isAnnotationPresent( Immutable.class ) );
OptimisticLock lockAnn = property.getAnnotation( OptimisticLock.class );
if ( lockAnn != null ) collection.setOptimisticLocked( !lockAnn.excluded() );
//work on association
boolean isMappedBy = !BinderHelper.isEmptyAnnotationValue( mappedBy );
final OptimisticLock lockAnn = property.getAnnotation( OptimisticLock.class );
final boolean includeInOptimisticLockChecks = ( lockAnn != null )
? ! lockAnn.excluded()
: ! isMappedBy;
collection.setOptimisticLocked( includeInOptimisticLockChecks );
Persister persisterAnn = property.getAnnotation( Persister.class );
if ( persisterAnn != null ) {
@ -512,9 +519,6 @@ public abstract class CollectionBinder {
collection.setLoaderName( loader.namedQuery() );
}
//work on association
boolean isMappedBy = !BinderHelper.isEmptyAnnotationValue( mappedBy );
if (isMappedBy
&& (property.isAnnotationPresent( JoinColumn.class )
|| property.isAnnotationPresent( JoinColumns.class )

View File

@ -48,12 +48,14 @@ import org.hibernate.cfg.PropertyHolder;
import org.hibernate.cfg.PropertyPreloadedData;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.KeyValue;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.PropertyGeneration;
import org.hibernate.mapping.RootClass;
import org.hibernate.mapping.SimpleValue;
import org.hibernate.mapping.ToOne;
import org.hibernate.mapping.Value;
/**
@ -296,27 +298,46 @@ public class PropertyBinder {
prop.setInsertable( insertable );
prop.setUpdateable( updatable );
OptimisticLock lockAnn = property != null ?
property.getAnnotation( OptimisticLock.class ) :
null;
if ( lockAnn != null ) {
prop.setOptimisticLocked( !lockAnn.excluded() );
//TODO this should go to the core as a mapping validation checking
if ( lockAnn.excluded() && (
property.isAnnotationPresent( javax.persistence.Version.class )
|| property.isAnnotationPresent( Id.class )
|| property.isAnnotationPresent( EmbeddedId.class ) ) ) {
throw new AnnotationException(
"@OptimisticLock.exclude=true incompatible with @Id, @EmbeddedId and @Version: "
+ StringHelper.qualify( holder.getPath(), name )
);
}
// this is already handled for collections in CollectionBinder...
if ( Collection.class.isInstance( value ) ) {
prop.setOptimisticLocked( ( (Collection) value ).isOptimisticLocked() );
}
else {
final OptimisticLock lockAnn = property != null
? property.getAnnotation( OptimisticLock.class )
: null;
if ( lockAnn != null ) {
//TODO this should go to the core as a mapping validation checking
if ( lockAnn.excluded() && (
property.isAnnotationPresent( javax.persistence.Version.class )
|| property.isAnnotationPresent( Id.class )
|| property.isAnnotationPresent( EmbeddedId.class ) ) ) {
throw new AnnotationException(
"@OptimisticLock.exclude=true incompatible with @Id, @EmbeddedId and @Version: "
+ StringHelper.qualify( holder.getPath(), name )
);
}
}
final boolean isOwnedValue = !isToOneValue( value ) || insertable; // && updatable as well???
final boolean includeInOptimisticLockChecks = ( lockAnn != null )
? ! lockAnn.excluded()
: isOwnedValue;
prop.setOptimisticLocked( includeInOptimisticLockChecks );
}
LOG.tracev( "Cascading {0} with {1}", name, cascade );
this.mappingProperty = prop;
return prop;
}
private boolean isCollection(Value value) {
return Collection.class.isInstance( value );
}
private boolean isToOneValue(Value value) {
return ToOne.class.isInstance( value );
}
public void setProperty(XProperty property) {
this.property = property;
}

View File

@ -44,7 +44,6 @@ public class JpaSpecVersionValueUpdatingTest extends BaseCoreFunctionalTestCase
}
@Test
@FailureExpected( jiraKey = "HHH-7138" )
public void testVersionNotIncrementedOnModificationOfNonOwningCollectionNonCascaded() {
Session session = openSession();
session.beginTransaction();
@ -98,12 +97,6 @@ public class JpaSpecVersionValueUpdatingTest extends BaseCoreFunctionalTestCase
Customer customer = new Customer();
customer.id = 1L;
Order order = new Order();
order.id = 1L;
order.customer = customer;
customer.orders.add( order );
Session session = openSession();
session.beginTransaction();
session.save( customer );
@ -112,6 +105,19 @@ public class JpaSpecVersionValueUpdatingTest extends BaseCoreFunctionalTestCase
long initial = customer.version;
session = openSession();
session.beginTransaction();
customer = (Customer) session.get( Customer.class, 1L );
assertEquals( initial, customer.version );
Order order = new Order();
order.id = 1L;
order.customer = customer;
customer.orders.add( order );
session.getTransaction().commit();
session.close();
assertEquals( initial, customer.version );
session = openSession();
session.beginTransaction();
customer = (Customer) session.get( Customer.class, 1L );
@ -122,6 +128,7 @@ public class JpaSpecVersionValueUpdatingTest extends BaseCoreFunctionalTestCase
session.getTransaction().commit();
session.close();
assertEquals( initial, customer.version );
session = openSession();
session.beginTransaction();