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 1dd59b2dff
commit 6c896b7dee
4 changed files with 36 additions and 6 deletions

View File

@ -779,8 +779,8 @@ private String generateUnexpectedSessionStateMessage(SharedSessionContractImplem
@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
@ -790,7 +790,7 @@ public boolean needsRecreate(CollectionPersister persister) {
// 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();
}
@ -798,8 +798,8 @@ public boolean needsRecreate(CollectionPersister persister) {
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

@ -394,6 +394,11 @@ public boolean hasNotNullProperty() {
return true;
}
@Override
public boolean hasNullProperty() {
return false;
}
@Override
public Type[] getSubtypes() {
return new Type[] {discriminatorType, identifierType };

View File

@ -66,6 +66,7 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
private final boolean isKey;
private boolean hasNotNullProperty;
private final CompositeUserType<Object> compositeUserType;
private boolean hasNullProperty;
private EmbeddableValuedModelPart mappingModelPart;
@ -91,9 +92,12 @@ public ComponentType(Component component, int[] originalPropertyOrder, MetadataB
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++;
}
@ -814,6 +818,11 @@ public boolean hasNotNullProperty() {
return hasNotNullProperty;
}
@Override
public boolean hasNullProperty() {
return hasNullProperty;
}
@Override
public Class<?> getBindableJavaType() {
return getReturnedClass();

View File

@ -138,6 +138,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.
*