HHH-9834 - Fix failure when deleting and inserting values with the same Map key.
This commit is contained in:
parent
36e75f4a4d
commit
1d41a3f761
|
@ -449,7 +449,7 @@ public final class CollectionMetadataGenerator {
|
|||
mainGenerator.getAuditStrategy(),
|
||||
referencingIdData,
|
||||
auditMiddleEntityName,
|
||||
isEmbeddableElementType()
|
||||
isRevisionTypeInId()
|
||||
);
|
||||
|
||||
// Adding the XML mapping for the referencing entity, if the relation isn't inverse.
|
||||
|
@ -471,7 +471,7 @@ public final class CollectionMetadataGenerator {
|
|||
queryGeneratorBuilder,
|
||||
referencedPrefix,
|
||||
propertyAuditingData.getJoinTable().inverseJoinColumns(),
|
||||
isCollectionElementKeyProperty()
|
||||
!isLobMapElementType()
|
||||
);
|
||||
|
||||
// ******
|
||||
|
@ -723,6 +723,7 @@ public final class CollectionMetadataGenerator {
|
|||
MiddleComponentData indexComponentData) {
|
||||
final Type type = propertyValue.getType();
|
||||
final boolean embeddableElementType = isEmbeddableElementType();
|
||||
final boolean lobMapElementType = isLobMapElementType();
|
||||
if ( type instanceof SortedSetType ) {
|
||||
currentMapper.addComposite(
|
||||
propertyAuditingData.getPropertyData(),
|
||||
|
@ -761,7 +762,7 @@ public final class CollectionMetadataGenerator {
|
|||
elementComponentData,
|
||||
indexComponentData,
|
||||
propertyValue.getComparator(),
|
||||
embeddableElementType
|
||||
embeddableElementType || lobMapElementType
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -775,7 +776,7 @@ public final class CollectionMetadataGenerator {
|
|||
MapProxy.class,
|
||||
elementComponentData,
|
||||
indexComponentData,
|
||||
embeddableElementType
|
||||
embeddableElementType || lobMapElementType
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -854,9 +855,9 @@ public final class CollectionMetadataGenerator {
|
|||
|
||||
// Adding the revision type property to the entity xml.
|
||||
mainGenerator.addRevisionType(
|
||||
isEmbeddableElementType() ? middleEntityXmlId : middleEntityXml,
|
||||
isRevisionTypeInId() ? middleEntityXmlId : middleEntityXml,
|
||||
middleEntityXml,
|
||||
isEmbeddableElementType()
|
||||
isRevisionTypeInId()
|
||||
);
|
||||
|
||||
// All other properties should also be part of the primary key of the middle entity.
|
||||
|
@ -1023,20 +1024,27 @@ public final class CollectionMetadataGenerator {
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks whether the collection element should participate in the primary key association. This
|
||||
* is only applicable for non-component, non-associative collection element types.
|
||||
* Returns whether the revision type column part of the collection table's primary key.
|
||||
*
|
||||
* @return {@code true} if should be part of the primary key, {@code false} if not.
|
||||
* @return {@code true} if the revision type should be part of the primary key, otherwise {@code false}.
|
||||
*/
|
||||
private boolean isCollectionElementKeyProperty() {
|
||||
// When List or Set are used, the element will always be part of the primary key.
|
||||
// When using a Map, the element isn't required as the Map Key will suffice.
|
||||
private boolean isRevisionTypeInId() {
|
||||
return isEmbeddableElementType() || isLobMapElementType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the collection is a map-type and that the map element is defined as a Clob/NClob type.
|
||||
*
|
||||
* @return {@code true} if the element is a Clob/NClob type, otherwise {@code false}.
|
||||
*/
|
||||
private boolean isLobMapElementType() {
|
||||
if ( propertyValue instanceof org.hibernate.mapping.Map ) {
|
||||
final Type type = propertyValue.getElement().getType();
|
||||
// we're only interested in basic types
|
||||
if ( !type.isComponentType() && !type.isAssociationType() ) {
|
||||
return !( type instanceof MaterializedClobType || type instanceof MaterializedNClobType );
|
||||
return ( type instanceof MaterializedClobType ) || ( type instanceof MaterializedNClobType );
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,9 @@ import org.hibernate.property.access.spi.Getter;
|
|||
import org.hibernate.sql.Update;
|
||||
import org.hibernate.type.CollectionType;
|
||||
import org.hibernate.type.ComponentType;
|
||||
import org.hibernate.type.MapType;
|
||||
import org.hibernate.type.MaterializedClobType;
|
||||
import org.hibernate.type.MaterializedNClobType;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
import static org.hibernate.envers.internal.entities.mapper.relation.query.QueryConstants.MIDDLE_ENTITY_ALIAS;
|
||||
|
@ -260,25 +263,8 @@ public class ValidityAuditStrategy implements AuditStrategy {
|
|||
}
|
||||
}
|
||||
|
||||
final SessionFactoryImplementor sessionFactory = ( (SessionImplementor) session ).getFactory();
|
||||
final Type propertyType = sessionFactory.getMetamodel().entityPersister( entityName ).getPropertyType( propertyName );
|
||||
if ( propertyType.isCollectionType() ) {
|
||||
CollectionType collectionPropertyType = (CollectionType) propertyType;
|
||||
// Handling collection of components.
|
||||
if ( collectionPropertyType.getElementType( sessionFactory ) instanceof ComponentType ) {
|
||||
// Adding restrictions to compare data outside of primary key.
|
||||
// todo: is it necessary that non-primary key attributes be compared?
|
||||
for ( Map.Entry<String, Object> dataEntry : persistentCollectionChangeData.getData().entrySet() ) {
|
||||
if ( !originalIdPropName.equals( dataEntry.getKey() ) ) {
|
||||
if ( dataEntry.getValue() != null ) {
|
||||
qb.getRootParameters().addWhereWithParam( dataEntry.getKey(), true, "=", dataEntry.getValue() );
|
||||
}
|
||||
else {
|
||||
qb.getRootParameters().addNullRestriction( dataEntry.getKey(), true );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( isNonIdentifierWhereConditionsRequired( entityName, propertyName, (SessionImplementor) session ) ) {
|
||||
addNonIdentifierWhereConditions( qb, persistentCollectionChangeData.getData(), originalIdPropName );
|
||||
}
|
||||
|
||||
addEndRevisionNullRestriction( auditEntitiesConfiguration, qb.getRootParameters() );
|
||||
|
@ -299,6 +285,37 @@ public class ValidityAuditStrategy implements AuditStrategy {
|
|||
sessionCacheCleaner.scheduleAuditDataRemoval( session, persistentCollectionChangeData.getData() );
|
||||
}
|
||||
|
||||
private boolean isNonIdentifierWhereConditionsRequired(String entityName, String propertyName, SessionImplementor session) {
|
||||
final Type propertyType = session.getSessionFactory().getMetamodel().entityPersister( entityName ).getPropertyType( propertyName );
|
||||
if ( propertyType.isCollectionType() ) {
|
||||
final CollectionType collectionType = (CollectionType) propertyType;
|
||||
final Type collectionElementType = collectionType.getElementType( session.getSessionFactory() );
|
||||
if ( collectionElementType instanceof ComponentType ) {
|
||||
// required for Embeddables
|
||||
return true;
|
||||
}
|
||||
else if ( collectionElementType instanceof MaterializedClobType || collectionElementType instanceof MaterializedNClobType ) {
|
||||
// for Map<> using @Lob annotations
|
||||
return collectionType instanceof MapType;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void addNonIdentifierWhereConditions(QueryBuilder qb, Map<String, Object> data, String originalIdPropertyName) {
|
||||
final Parameters parameters = qb.getRootParameters();
|
||||
for ( Map.Entry<String, Object> entry : data.entrySet() ) {
|
||||
if ( !originalIdPropertyName.equals( entry.getKey() ) ) {
|
||||
if ( entry.getValue() != null ) {
|
||||
parameters.addWhereWithParam( entry.getKey(), true, "=", entry.getValue() );
|
||||
}
|
||||
else {
|
||||
parameters.addNullRestriction( entry.getKey(), true );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addEndRevisionNullRestriction(AuditEntitiesConfiguration auditEntitiesConfiguration, Parameters rootParameters) {
|
||||
rootParameters.addWhere( auditEntitiesConfiguration.getRevisionEndFieldName(), true, "is", "null", false );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue