mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-16 16:15:06 +00:00
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 @@ private void addWithMiddleTable() {
|
|||||||
mainGenerator.getAuditStrategy(),
|
mainGenerator.getAuditStrategy(),
|
||||||
referencingIdData,
|
referencingIdData,
|
||||||
auditMiddleEntityName,
|
auditMiddleEntityName,
|
||||||
isEmbeddableElementType()
|
isRevisionTypeInId()
|
||||||
);
|
);
|
||||||
|
|
||||||
// Adding the XML mapping for the referencing entity, if the relation isn't inverse.
|
// Adding the XML mapping for the referencing entity, if the relation isn't inverse.
|
||||||
@ -471,7 +471,7 @@ private void addWithMiddleTable() {
|
|||||||
queryGeneratorBuilder,
|
queryGeneratorBuilder,
|
||||||
referencedPrefix,
|
referencedPrefix,
|
||||||
propertyAuditingData.getJoinTable().inverseJoinColumns(),
|
propertyAuditingData.getJoinTable().inverseJoinColumns(),
|
||||||
isCollectionElementKeyProperty()
|
!isLobMapElementType()
|
||||||
);
|
);
|
||||||
|
|
||||||
// ******
|
// ******
|
||||||
@ -723,6 +723,7 @@ private void addMapper(
|
|||||||
MiddleComponentData indexComponentData) {
|
MiddleComponentData indexComponentData) {
|
||||||
final Type type = propertyValue.getType();
|
final Type type = propertyValue.getType();
|
||||||
final boolean embeddableElementType = isEmbeddableElementType();
|
final boolean embeddableElementType = isEmbeddableElementType();
|
||||||
|
final boolean lobMapElementType = isLobMapElementType();
|
||||||
if ( type instanceof SortedSetType ) {
|
if ( type instanceof SortedSetType ) {
|
||||||
currentMapper.addComposite(
|
currentMapper.addComposite(
|
||||||
propertyAuditingData.getPropertyData(),
|
propertyAuditingData.getPropertyData(),
|
||||||
@ -761,7 +762,7 @@ else if ( type instanceof SortedMapType ) {
|
|||||||
elementComponentData,
|
elementComponentData,
|
||||||
indexComponentData,
|
indexComponentData,
|
||||||
propertyValue.getComparator(),
|
propertyValue.getComparator(),
|
||||||
embeddableElementType
|
embeddableElementType || lobMapElementType
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -775,7 +776,7 @@ else if ( type instanceof MapType ) {
|
|||||||
MapProxy.class,
|
MapProxy.class,
|
||||||
elementComponentData,
|
elementComponentData,
|
||||||
indexComponentData,
|
indexComponentData,
|
||||||
embeddableElementType
|
embeddableElementType || lobMapElementType
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -854,9 +855,9 @@ private Element createMiddleEntityXml(String auditMiddleTableName, String auditM
|
|||||||
|
|
||||||
// Adding the revision type property to the entity xml.
|
// Adding the revision type property to the entity xml.
|
||||||
mainGenerator.addRevisionType(
|
mainGenerator.addRevisionType(
|
||||||
isEmbeddableElementType() ? middleEntityXmlId : middleEntityXml,
|
isRevisionTypeInId() ? middleEntityXmlId : middleEntityXml,
|
||||||
middleEntityXml,
|
middleEntityXml,
|
||||||
isEmbeddableElementType()
|
isRevisionTypeInId()
|
||||||
);
|
);
|
||||||
|
|
||||||
// All other properties should also be part of the primary key of the middle entity.
|
// All other properties should also be part of the primary key of the middle entity.
|
||||||
@ -1023,20 +1024,27 @@ public Table getTable() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the collection element should participate in the primary key association. This
|
* Returns whether the revision type column part of the collection table's primary key.
|
||||||
* is only applicable for non-component, non-associative collection element types.
|
|
||||||
*
|
*
|
||||||
* @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() {
|
private boolean isRevisionTypeInId() {
|
||||||
// When List or Set are used, the element will always be part of the primary key.
|
return isEmbeddableElementType() || isLobMapElementType();
|
||||||
// When using a Map, the element isn't required as the Map Key will suffice.
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 ) {
|
if ( propertyValue instanceof org.hibernate.mapping.Map ) {
|
||||||
final Type type = propertyValue.getElement().getType();
|
final Type type = propertyValue.getElement().getType();
|
||||||
|
// we're only interested in basic types
|
||||||
if ( !type.isComponentType() && !type.isAssociationType() ) {
|
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.sql.Update;
|
import org.hibernate.sql.Update;
|
||||||
import org.hibernate.type.CollectionType;
|
import org.hibernate.type.CollectionType;
|
||||||
import org.hibernate.type.ComponentType;
|
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 org.hibernate.type.Type;
|
||||||
|
|
||||||
import static org.hibernate.envers.internal.entities.mapper.relation.query.QueryConstants.MIDDLE_ENTITY_ALIAS;
|
import static org.hibernate.envers.internal.entities.mapper.relation.query.QueryConstants.MIDDLE_ENTITY_ALIAS;
|
||||||
@ -260,25 +263,8 @@ public void performCollectionChange(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final SessionFactoryImplementor sessionFactory = ( (SessionImplementor) session ).getFactory();
|
if ( isNonIdentifierWhereConditionsRequired( entityName, propertyName, (SessionImplementor) session ) ) {
|
||||||
final Type propertyType = sessionFactory.getMetamodel().entityPersister( entityName ).getPropertyType( propertyName );
|
addNonIdentifierWhereConditions( qb, persistentCollectionChangeData.getData(), originalIdPropName );
|
||||||
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 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addEndRevisionNullRestriction( auditEntitiesConfiguration, qb.getRootParameters() );
|
addEndRevisionNullRestriction( auditEntitiesConfiguration, qb.getRootParameters() );
|
||||||
@ -299,6 +285,37 @@ public void performCollectionChange(
|
|||||||
sessionCacheCleaner.scheduleAuditDataRemoval( session, persistentCollectionChangeData.getData() );
|
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) {
|
private void addEndRevisionNullRestriction(AuditEntitiesConfiguration auditEntitiesConfiguration, Parameters rootParameters) {
|
||||||
rootParameters.addWhere( auditEntitiesConfiguration.getRevisionEndFieldName(), true, "is", "null", false );
|
rootParameters.addWhere( auditEntitiesConfiguration.getRevisionEndFieldName(), true, "is", "null", false );
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user