HHH-17257 ElementCollection is missing elements after update if embeddable type has primitive columns marked as nullable

This commit is contained in:
Andrea Boriero 2023-09-26 09:30:30 +02:00 committed by Andrea Boriero
parent 2857491acf
commit 43c0d96ba4
4 changed files with 36 additions and 6 deletions

View File

@ -782,8 +782,8 @@ public abstract class AbstractPersistentCollection<E> implements Serializable, P
@Override
public boolean needsRecreate(CollectionPersister persister) {
// Workaround for situations like HHH-7072. If the collection element is a component that consists entirely
// of nullable properties, we currently have to forcefully recreate the entire collection. See the use
// Workaround for situations like HHH-7072. If the collection element is a component that consists
// nullable properties, we currently have to forcefully recreate the entire collection. See the use
// of hasNotNullableColumns in the AbstractCollectionPersister constructor for more info. In order to delete
// row-by-row, that would require SQL like "WHERE ( COL = ? OR ( COL is null AND ? is null ) )", rather than
// the current "WHERE COL = ?" (fails for null for most DBs). Note that
@ -793,7 +793,7 @@ public abstract class AbstractPersistentCollection<E> implements Serializable, P
// Selecting a type used in where part of update statement
// (must match condition in org.hibernate.persister.collection.BasicCollectionPersister#doUpdateRows).
// See HHH-9474
Type whereType;
final Type whereType;
if ( persister.hasIndex() ) {
whereType = persister.getIndexType();
}
@ -801,8 +801,8 @@ public abstract class AbstractPersistentCollection<E> implements Serializable, P
whereType = persister.getElementType();
}
if ( whereType instanceof CompositeType ) {
CompositeType componentIndexType = (CompositeType) whereType;
return !componentIndexType.hasNotNullProperty();
final CompositeType componentIndexType = (CompositeType) whereType;
return componentIndexType.hasNullProperty();
}
return false;
}

View File

@ -395,6 +395,11 @@ public class AnyType extends AbstractType implements CompositeType, AssociationT
return true;
}
@Override
public boolean hasNullProperty() {
return false;
}
@Override
public Type[] getSubtypes() {
return new Type[] {discriminatorType, identifierType };

View File

@ -63,6 +63,7 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
private final boolean isAggregate;
private final boolean isKey;
private boolean hasNotNullProperty;
private boolean hasNullProperty;
private EmbeddableValuedModelPart mappingModelPart;
@ -97,9 +98,12 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
this.propertyNullability[i] = property.isOptional();
this.cascade[i] = property.getCascadeStyle();
this.joinedFetch[i] = property.getValue().getFetchMode();
if ( !propertyNullability[i] ) {
if ( !property.isOptional() ) {
hasNotNullProperty = true;
}
else {
hasNullProperty = true;
}
i++;
}
}
@ -762,6 +766,11 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
return hasNotNullProperty;
}
@Override
public boolean hasNullProperty() {
return hasNullProperty;
}
@Override
public Class<?> getBindableJavaType() {
return getReturnedClass();

View File

@ -158,6 +158,22 @@ public interface CompositeType extends Type {
*/
boolean hasNotNullProperty();
/**
* Convenience method to quickly check if {@link #getPropertyNullability} contains a nullable sub-properties.
*
* @return {@code true} if any of the properties are nullable as indicated by {@link #getPropertyNullability},
* {@code false} otherwise.
*/
default boolean hasNullProperty() {
final boolean[] propertyNullability = getPropertyNullability();
for ( int i = 0; i < propertyNullability.length; i++ ) {
if ( propertyNullability[i] ) {
return true;
}
}
return false;
}
/**
* Convenience method for locating the property index for a given property name.
*