Skip to content

Commit e8b88f5

Browse files
harikantvermavladmihalcea
authored andcommitted
HHH-13068 - "order_inserts = true" causes FK Violation when inserting Self Referential Entity with Single_Table Inherited Entities
1 parent 5e30e50 commit e8b88f5

File tree

2 files changed

+490
-10
lines changed

2 files changed

+490
-10
lines changed

hibernate-core/src/main/java/org/hibernate/engine/spi/ActionQueue.java

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,7 +1111,8 @@ boolean hasAnyChildEntityNames(BatchIdentifier batchIdentifier) {
11111111
boolean hasParent(BatchIdentifier batchIdentifier) {
11121112
return (
11131113
parent == batchIdentifier
1114-
|| ( parentEntityNames.contains( batchIdentifier.getEntityName() ) )
1114+
|| parentEntityNames.contains( batchIdentifier.getEntityName() )
1115+
|| ( parentEntityNames.contains( batchIdentifier.getRootEntityName() ) && !this.getEntityName().equals( batchIdentifier.getRootEntityName() ) )
11151116
|| parent != null && parent.hasParent( batchIdentifier, new ArrayList<>() )
11161117
);
11171118
}
@@ -1168,7 +1169,6 @@ public void sort(List<AbstractEntityInsertAction> insertions) {
11681169
addParentChildEntityNames( action, batchIdentifier );
11691170
addToBatch( batchIdentifier, action );
11701171
}
1171-
insertions.clear();
11721172

11731173
// Examine each entry in the batch list, and build the dependency graph.
11741174
for ( int i = 0; i < latestBatches.size(); i++ ) {
@@ -1217,7 +1217,12 @@ public void sort(List<AbstractEntityInsertAction> insertions) {
12171217
for ( int j = i + 1; j < latestBatches.size(); j++ ) {
12181218
BatchIdentifier nextBatchIdentifier = latestBatches.get( j );
12191219

1220-
if ( batchIdentifier.hasParent( nextBatchIdentifier ) && !nextBatchIdentifier.hasParent( batchIdentifier ) ) {
1220+
if ( batchIdentifier.hasParent( nextBatchIdentifier ) ) {
1221+
if( nextBatchIdentifier.hasParent( batchIdentifier ) ) {
1222+
//cycle detected, no need to continue
1223+
break sort;
1224+
}
1225+
12211226
latestBatches.remove( batchIdentifier );
12221227
latestBatches.add( j, batchIdentifier );
12231228

@@ -1235,9 +1240,13 @@ public void sort(List<AbstractEntityInsertAction> insertions) {
12351240
}
12361241

12371242
// Now, rebuild the insertions list. There is a batch for each entry in the name list.
1238-
for ( BatchIdentifier rootIdentifier : latestBatches ) {
1239-
List<AbstractEntityInsertAction> batch = actionBatches.get( rootIdentifier );
1240-
insertions.addAll( batch );
1243+
if ( sorted ) {
1244+
insertions.clear();
1245+
1246+
for ( BatchIdentifier rootIdentifier : latestBatches ) {
1247+
List<AbstractEntityInsertAction> batch = actionBatches.get( rootIdentifier );
1248+
insertions.addAll( batch );
1249+
}
12411250
}
12421251
}
12431252

@@ -1252,17 +1261,27 @@ private void addParentChildEntityNames(AbstractEntityInsertAction action, BatchI
12521261
ClassMetadata classMetadata = action.getPersister().getClassMetadata();
12531262
if ( classMetadata != null ) {
12541263
Type[] propertyTypes = classMetadata.getPropertyTypes();
1264+
Type identifierType = classMetadata.getIdentifierType();
12551265

12561266
for ( int i = 0; i < propertyValues.length; i++ ) {
12571267
Object value = propertyValues[i];
12581268
Type type = propertyTypes[i];
12591269
addParentChildEntityNameByPropertyAndValue( action, batchIdentifier, type, value );
12601270
}
1271+
1272+
if ( identifierType.isComponentType() ) {
1273+
CompositeType compositeType = (CompositeType) identifierType;
1274+
Type[] compositeIdentifierTypes = compositeType.getSubtypes();
1275+
1276+
for ( Type type : compositeIdentifierTypes ) {
1277+
addParentChildEntityNameByPropertyAndValue( action, batchIdentifier, type, null );
1278+
}
1279+
}
12611280
}
12621281
}
12631282

12641283
private void addParentChildEntityNameByPropertyAndValue(AbstractEntityInsertAction action, BatchIdentifier batchIdentifier, Type type, Object value) {
1265-
if ( type.isEntityType() && value != null ) {
1284+
if ( type.isEntityType() ) {
12661285
final EntityType entityType = (EntityType) type;
12671286
final String entityName = entityType.getName();
12681287
final String rootEntityName = action.getSession().getFactory().getMetamodel().entityPersister( entityName ).getRootEntityName();
@@ -1276,17 +1295,26 @@ private void addParentChildEntityNameByPropertyAndValue(AbstractEntityInsertActi
12761295
}
12771296
}
12781297
else {
1279-
batchIdentifier.getParentEntityNames().add( entityName );
1298+
if ( !batchIdentifier.getEntityName().equals( entityName ) ) {
1299+
batchIdentifier.getParentEntityNames().add( entityName );
1300+
}
1301+
if ( value != null ) {
1302+
String valueClass = value.getClass().getName();
1303+
if ( !valueClass.equals( entityName ) ) {
1304+
batchIdentifier.getParentEntityNames().add( valueClass );
1305+
}
1306+
}
12801307
if ( !rootEntityName.equals( entityName ) ) {
12811308
batchIdentifier.getParentEntityNames().add( rootEntityName );
12821309
}
12831310
}
12841311
}
1285-
else if ( type.isCollectionType() && value != null ) {
1312+
else if ( type.isCollectionType() ) {
12861313
CollectionType collectionType = (CollectionType) type;
12871314
final SessionFactoryImplementor sessionFactory = ( (SessionImplementor) action.getSession() )
12881315
.getSessionFactory();
1289-
if ( collectionType.getElementType( sessionFactory ).isEntityType() ) {
1316+
if ( collectionType.getElementType( sessionFactory ).isEntityType() &&
1317+
!sessionFactory.getMetamodel().collectionPersister( collectionType.getRole() ).isManyToMany() ) {
12901318
String entityName = collectionType.getAssociatedEntityName( sessionFactory );
12911319
String rootEntityName = action.getSession().getFactory().getMetamodel().entityPersister( entityName ).getRootEntityName();
12921320
batchIdentifier.getChildEntityNames().add( entityName );

0 commit comments

Comments
 (0)