HHH-8276 - Fix AnyType handling during Nullability checking

This commit is contained in:
Steve Ebersole 2013-10-01 18:07:56 -05:00
parent 479b873f5b
commit edc4a04a63

View File

@ -139,37 +139,23 @@ else if ( value != null ) {
* @throws HibernateException error while getting subcomponent values * @throws HibernateException error while getting subcomponent values
*/ */
private String checkSubElementsNullability(Type propertyType, Object value) throws HibernateException { private String checkSubElementsNullability(Type propertyType, Object value) throws HibernateException {
// IMPL NOTE : we currently skip checking "any" and "many to any" mappings. This is not the best solution.
//
// The problem I ran into with performing the checks on "any" and "many to any" mappings had to do with
// cascaded saves of transient associated entities not yet having assigned the identifier (this was
// specifically in the "many to any" case).
if ( propertyType.isAnyType() ) {
return null;
}
if ( propertyType.isComponentType() ) { if ( propertyType.isComponentType() ) {
return checkComponentNullability( value, (CompositeType) propertyType ); return checkComponentNullability( value, (CompositeType) propertyType );
} }
if ( propertyType.isCollectionType() ) { if ( propertyType.isCollectionType() ) {
//persistent collections may have components // persistent collections may have components
final CollectionType collectionType = (CollectionType) propertyType; final CollectionType collectionType = (CollectionType) propertyType;
final Type collectionElementType = collectionType.getElementType( session.getFactory() ); final Type collectionElementType = collectionType.getElementType( session.getFactory() );
if ( collectionElementType.isAnyType() ) {
return null;
}
if ( collectionElementType.isComponentType() ) { if ( collectionElementType.isComponentType() ) {
//check for all components values in the collection // check for all components values in the collection
final CompositeType componentType = (CompositeType) collectionElementType; final CompositeType componentType = (CompositeType) collectionElementType;
final Iterator itr = CascadingActions.getLoadedElementsIterator( session, collectionType, value ); final Iterator itr = CascadingActions.getLoadedElementsIterator( session, collectionType, value );
while ( itr.hasNext() ) { while ( itr.hasNext() ) {
final Object compValue = itr.next(); final Object compositeElement = itr.next();
if ( compValue != null ) { if ( compositeElement != null ) {
return checkComponentNullability( compValue, componentType ); return checkComponentNullability( compositeElement, componentType );
} }
} }
} }
@ -183,29 +169,39 @@ private String checkSubElementsNullability(Type propertyType, Object value) thro
* nullability or null if none * nullability or null if none
* *
* @param value component properties * @param value component properties
* @param compType component not-nullable type * @param compositeType component not-nullable type
* *
* @return property path * @return property path
* @throws HibernateException error while getting subcomponent values * @throws HibernateException error while getting subcomponent values
*/ */
private String checkComponentNullability(Object value, CompositeType compType) throws HibernateException { private String checkComponentNullability(Object value, CompositeType compositeType) throws HibernateException {
/* will check current level if some of them are not null // IMPL NOTE : we currently skip checking "any" and "many to any" mappings.
* or sublevels if they exist //
*/ // This is not the best solution. But atm there is a mismatch between AnyType#getPropertyNullability
final boolean[] nullability = compType.getPropertyNullability(); // and the fact that cascaded-saves for "many to any" mappings are not performed until after this nullability
// check. So the nullability check fails for transient entity elements with generated identifiers because
// the identifier is not yet generated/assigned (is null)
//
// The more correct fix would be to cascade saves of the many-to-any elements before the Nullability checking
if ( compositeType.isAnyType() ) {
return null;
}
final boolean[] nullability = compositeType.getPropertyNullability();
if ( nullability != null ) { if ( nullability != null ) {
//do the test //do the test
final Object[] subValues = compType.getPropertyValues( value, session ); final Object[] subValues = compositeType.getPropertyValues( value, session );
final Type[] propertyTypes = compType.getSubtypes(); final Type[] propertyTypes = compositeType.getSubtypes();
for ( int i = 0; i < subValues.length; i++ ) { for ( int i = 0; i < subValues.length; i++ ) {
final Object subValue = subValues[i]; final Object subValue = subValues[i];
if ( !nullability[i] && subValue==null ) { if ( !nullability[i] && subValue==null ) {
return compType.getPropertyNames()[i]; return compositeType.getPropertyNames()[i];
} }
else if ( subValue != null ) { else if ( subValue != null ) {
final String breakProperties = checkSubElementsNullability( propertyTypes[i], subValue ); final String breakProperties = checkSubElementsNullability( propertyTypes[i], subValue );
if ( breakProperties != null ) { if ( breakProperties != null ) {
return buildPropertyPath( compType.getPropertyNames()[i], breakProperties ); return buildPropertyPath( compositeType.getPropertyNames()[i], breakProperties );
} }
} }
} }