Skip to content

Commit edc4a04

Browse files
committed
HHH-8276 - Fix AnyType handling during Nullability checking
1 parent 479b873 commit edc4a04

File tree

1 file changed

+25
-29
lines changed

1 file changed

+25
-29
lines changed

hibernate-core/src/main/java/org/hibernate/engine/internal/Nullability.java

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -139,37 +139,23 @@ else if ( value != null ) {
139139
* @throws HibernateException error while getting subcomponent values
140140
*/
141141
private String checkSubElementsNullability(Type propertyType, Object value) throws HibernateException {
142-
// IMPL NOTE : we currently skip checking "any" and "many to any" mappings. This is not the best solution.
143-
//
144-
// The problem I ran into with performing the checks on "any" and "many to any" mappings had to do with
145-
// cascaded saves of transient associated entities not yet having assigned the identifier (this was
146-
// specifically in the "many to any" case).
147-
148-
if ( propertyType.isAnyType() ) {
149-
return null;
150-
}
151-
152142
if ( propertyType.isComponentType() ) {
153143
return checkComponentNullability( value, (CompositeType) propertyType );
154144
}
155145

156146
if ( propertyType.isCollectionType() ) {
157-
//persistent collections may have components
147+
// persistent collections may have components
158148
final CollectionType collectionType = (CollectionType) propertyType;
159149
final Type collectionElementType = collectionType.getElementType( session.getFactory() );
160150

161-
if ( collectionElementType.isAnyType() ) {
162-
return null;
163-
}
164-
165151
if ( collectionElementType.isComponentType() ) {
166-
//check for all components values in the collection
152+
// check for all components values in the collection
167153
final CompositeType componentType = (CompositeType) collectionElementType;
168154
final Iterator itr = CascadingActions.getLoadedElementsIterator( session, collectionType, value );
169155
while ( itr.hasNext() ) {
170-
final Object compValue = itr.next();
171-
if ( compValue != null ) {
172-
return checkComponentNullability( compValue, componentType );
156+
final Object compositeElement = itr.next();
157+
if ( compositeElement != null ) {
158+
return checkComponentNullability( compositeElement, componentType );
173159
}
174160
}
175161
}
@@ -183,29 +169,39 @@ private String checkSubElementsNullability(Type propertyType, Object value) thro
183169
* nullability or null if none
184170
*
185171
* @param value component properties
186-
* @param compType component not-nullable type
172+
* @param compositeType component not-nullable type
187173
*
188174
* @return property path
189175
* @throws HibernateException error while getting subcomponent values
190176
*/
191-
private String checkComponentNullability(Object value, CompositeType compType) throws HibernateException {
192-
/* will check current level if some of them are not null
193-
* or sublevels if they exist
194-
*/
195-
final boolean[] nullability = compType.getPropertyNullability();
177+
private String checkComponentNullability(Object value, CompositeType compositeType) throws HibernateException {
178+
// IMPL NOTE : we currently skip checking "any" and "many to any" mappings.
179+
//
180+
// This is not the best solution. But atm there is a mismatch between AnyType#getPropertyNullability
181+
// and the fact that cascaded-saves for "many to any" mappings are not performed until after this nullability
182+
// check. So the nullability check fails for transient entity elements with generated identifiers because
183+
// the identifier is not yet generated/assigned (is null)
184+
//
185+
// The more correct fix would be to cascade saves of the many-to-any elements before the Nullability checking
186+
187+
if ( compositeType.isAnyType() ) {
188+
return null;
189+
}
190+
191+
final boolean[] nullability = compositeType.getPropertyNullability();
196192
if ( nullability != null ) {
197193
//do the test
198-
final Object[] subValues = compType.getPropertyValues( value, session );
199-
final Type[] propertyTypes = compType.getSubtypes();
194+
final Object[] subValues = compositeType.getPropertyValues( value, session );
195+
final Type[] propertyTypes = compositeType.getSubtypes();
200196
for ( int i = 0; i < subValues.length; i++ ) {
201197
final Object subValue = subValues[i];
202198
if ( !nullability[i] && subValue==null ) {
203-
return compType.getPropertyNames()[i];
199+
return compositeType.getPropertyNames()[i];
204200
}
205201
else if ( subValue != null ) {
206202
final String breakProperties = checkSubElementsNullability( propertyTypes[i], subValue );
207203
if ( breakProperties != null ) {
208-
return buildPropertyPath( compType.getPropertyNames()[i], breakProperties );
204+
return buildPropertyPath( compositeType.getPropertyNames()[i], breakProperties );
209205
}
210206
}
211207
}

0 commit comments

Comments
 (0)