Skip to content

Commit

Permalink
HHH-11714 - Fix ordered inserts with secondary tables and inheritance.
Browse files Browse the repository at this point in the history
(cherry picked from commit c6135f2)
  • Loading branch information
Naros authored and gbadner committed Jan 26, 2018
1 parent 0a9aa13 commit 80f1a6e
Showing 1 changed file with 52 additions and 10 deletions.
Expand Up @@ -1018,14 +1018,15 @@ private static class InsertActionSorter implements ExecutableList.Sorter<Abstrac
private static class BatchIdentifier {

private final String entityName;
private final String rootEntityName;

private Set<String> parentEntityNames = new HashSet<String>( );

private Set<String> childEntityNames = new HashSet<String>( );

public BatchIdentifier(
String entityName) {
public BatchIdentifier(String entityName, String rootEntityName) {
this.entityName = entityName;
this.rootEntityName = rootEntityName;
}

@Override
Expand All @@ -1049,13 +1050,35 @@ public String getEntityName() {
return entityName;
}

public String getRootEntityName() {
return rootEntityName;
}

public Set<String> getParentEntityNames() {
return parentEntityNames;
}

public Set<String> getChildEntityNames() {
return childEntityNames;
}

public boolean hasAnyParentEntityNames(String... entityNames) {
for ( String entityName : entityNames ) {
if ( parentEntityNames.contains( entityName ) ) {
return true;
}
}
return false;
}

public boolean hasAnyChildEntityNames(String... entityNames) {
for ( String entityName : entityNames ) {
if ( childEntityNames.contains( entityName ) ) {
return true;
}
}
return false;
}
}

// the mapping of entity names to their latest batch numbers.
Expand All @@ -1079,7 +1102,10 @@ public void sort(List<AbstractEntityInsertAction> insertions) {
this.actionBatches = new HashMap<BatchIdentifier, List<AbstractEntityInsertAction>>();

for ( AbstractEntityInsertAction action : insertions ) {
BatchIdentifier batchIdentifier = new BatchIdentifier( action.getEntityName() );
BatchIdentifier batchIdentifier = new BatchIdentifier(
action.getEntityName(),
action.getSession().getFactory().getMetamodel().entityPersister( action.getEntityName() ).getRootEntityName()
);

// the entity associated with the current action.
Object currentEntity = action.getInstance();
Expand All @@ -1100,11 +1126,12 @@ public void sort(List<AbstractEntityInsertAction> insertions) {
for ( int i = 0; i < latestBatches.size(); i++ ) {
BatchIdentifier batchIdentifier = latestBatches.get( i );
String entityName = batchIdentifier.getEntityName();
String rootEntityName = batchIdentifier.getRootEntityName();

//Make sure that child entries are not before parents
for ( int j = i - 1; j >= 0; j-- ) {
BatchIdentifier prevBatchIdentifier = latestBatches.get( j );
if ( prevBatchIdentifier.getParentEntityNames().contains( entityName ) ) {
if ( prevBatchIdentifier.hasAnyParentEntityNames( entityName, rootEntityName ) ) {
latestBatches.remove( batchIdentifier );
latestBatches.add( j, batchIdentifier );
}
Expand All @@ -1113,13 +1140,17 @@ public void sort(List<AbstractEntityInsertAction> insertions) {
//Make sure that parent entries are not after children
for ( int j = i + 1; j < latestBatches.size(); j++ ) {
BatchIdentifier nextBatchIdentifier = latestBatches.get( j );

final boolean nextBatchHasChild = nextBatchIdentifier.hasAnyChildEntityNames( entityName, rootEntityName );

final boolean batchHasChild = batchIdentifier.hasAnyChildEntityNames(
nextBatchIdentifier.getEntityName(), nextBatchIdentifier.getRootEntityName() );

final boolean batchHasParent = batchIdentifier.hasAnyParentEntityNames(
nextBatchIdentifier.getEntityName(), nextBatchIdentifier.getRootEntityName() );

//Take care of unidirectional @OneToOne associations but exclude bidirectional @ManyToMany
if ( nextBatchIdentifier.getChildEntityNames().contains( entityName ) &&
!batchIdentifier.getChildEntityNames().contains( nextBatchIdentifier.getEntityName() ) ) {
latestBatches.remove( batchIdentifier );
latestBatches.add( j, batchIdentifier );
}
else if ( batchIdentifier.getParentEntityNames().contains( nextBatchIdentifier.getEntityName() ) ) {
if ( ( nextBatchHasChild && !batchHasChild ) || batchHasParent ) {
latestBatches.remove( batchIdentifier );
latestBatches.add( j, batchIdentifier );
}
Expand Down Expand Up @@ -1152,21 +1183,32 @@ private void addParentChildEntityNames(AbstractEntityInsertAction action, BatchI
if ( type.isEntityType() && value != null ) {
EntityType entityType = (EntityType) type;
String entityName = entityType.getName();
String rootEntityName = action.getSession().getFactory().getMetamodel().entityPersister( entityName ).getRootEntityName();

if ( entityType.isOneToOne() &&
OneToOneType.class.cast( entityType ).getForeignKeyDirection() == ForeignKeyDirection.TO_PARENT ) {
batchIdentifier.getChildEntityNames().add( entityName );
if ( !rootEntityName.equals( entityName ) ) {
batchIdentifier.getChildEntityNames().add( rootEntityName );
}
}
else {
batchIdentifier.getParentEntityNames().add( entityName );
if ( !rootEntityName.equals( entityName ) ) {
batchIdentifier.getParentEntityNames().add( rootEntityName );
}
}
}
else if ( type.isCollectionType() && value != null ) {
CollectionType collectionType = (CollectionType) type;
final SessionFactoryImplementor sessionFactory = action.getSession().getFactory();
if ( collectionType.getElementType( sessionFactory ).isEntityType() ) {
String entityName = collectionType.getAssociatedEntityName( sessionFactory );
String rootEntityName = action.getSession().getFactory().getMetamodel().entityPersister( entityName ).getRootEntityName();
batchIdentifier.getChildEntityNames().add( entityName );
if ( !rootEntityName.equals( entityName ) ) {
batchIdentifier.getChildEntityNames().add( rootEntityName );
}
}
}
}
Expand Down

0 comments on commit 80f1a6e

Please sign in to comment.