HHH-14918 Always process components containing an ID copy as we would any other FK

This commit is contained in:
Yoann Rodière 2021-11-08 13:28:44 +01:00
parent 6c53a9d1ab
commit ccd58ee499
2 changed files with 14 additions and 64 deletions

View File

@ -57,7 +57,6 @@ import org.hibernate.boot.spi.MetadataBuildingOptions;
import org.hibernate.boot.spi.NaturalIdUniqueKeyBinder; import org.hibernate.boot.spi.NaturalIdUniqueKeyBinder;
import org.hibernate.cfg.AnnotatedClassType; import org.hibernate.cfg.AnnotatedClassType;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.CopyIdentifierComponentSecondPass;
import org.hibernate.cfg.CreateKeySecondPass; import org.hibernate.cfg.CreateKeySecondPass;
import org.hibernate.cfg.FkSecondPass; import org.hibernate.cfg.FkSecondPass;
import org.hibernate.cfg.IdGeneratorResolverSecondPass; import org.hibernate.cfg.IdGeneratorResolverSecondPass;
@ -1504,7 +1503,6 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
private ArrayList<IdGeneratorResolverSecondPass> idGeneratorResolverSecondPassList; private ArrayList<IdGeneratorResolverSecondPass> idGeneratorResolverSecondPassList;
private ArrayList<SetSimpleValueTypeSecondPass> setSimpleValueTypeSecondPassList; private ArrayList<SetSimpleValueTypeSecondPass> setSimpleValueTypeSecondPassList;
private ArrayList<CopyIdentifierComponentSecondPass> copyIdentifierComponentSecondPasList;
private ArrayList<FkSecondPass> fkSecondPassList; private ArrayList<FkSecondPass> fkSecondPassList;
private ArrayList<CreateKeySecondPass> createKeySecondPasList; private ArrayList<CreateKeySecondPass> createKeySecondPasList;
private ArrayList<SecondaryTableSecondPass> secondaryTableSecondPassList; private ArrayList<SecondaryTableSecondPass> secondaryTableSecondPassList;
@ -1526,9 +1524,6 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
else if ( secondPass instanceof SetSimpleValueTypeSecondPass ) { else if ( secondPass instanceof SetSimpleValueTypeSecondPass ) {
addSetSimpleValueTypeSecondPass( (SetSimpleValueTypeSecondPass) secondPass, onTopOfTheQueue ); addSetSimpleValueTypeSecondPass( (SetSimpleValueTypeSecondPass) secondPass, onTopOfTheQueue );
} }
else if ( secondPass instanceof CopyIdentifierComponentSecondPass ) {
addCopyIdentifierComponentSecondPass( (CopyIdentifierComponentSecondPass) secondPass, onTopOfTheQueue );
}
else if ( secondPass instanceof FkSecondPass ) { else if ( secondPass instanceof FkSecondPass ) {
addFkSecondPass( (FkSecondPass) secondPass, onTopOfTheQueue ); addFkSecondPass( (FkSecondPass) secondPass, onTopOfTheQueue );
} }
@ -1576,15 +1571,6 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
addSecondPass( secondPass, idGeneratorResolverSecondPassList, onTopOfTheQueue ); addSecondPass( secondPass, idGeneratorResolverSecondPassList, onTopOfTheQueue );
} }
private void addCopyIdentifierComponentSecondPass(
CopyIdentifierComponentSecondPass secondPass,
boolean onTopOfTheQueue) {
if ( copyIdentifierComponentSecondPasList == null ) {
copyIdentifierComponentSecondPasList = new ArrayList<>();
}
addSecondPass( secondPass, copyIdentifierComponentSecondPasList, onTopOfTheQueue );
}
private void addFkSecondPass(FkSecondPass secondPass, boolean onTopOfTheQueue) { private void addFkSecondPass(FkSecondPass secondPass, boolean onTopOfTheQueue) {
if ( fkSecondPassList == null ) { if ( fkSecondPassList == null ) {
fkSecondPassList = new ArrayList<>(); fkSecondPassList = new ArrayList<>();
@ -1635,8 +1621,6 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
processSecondPasses( implicitColumnNamingSecondPassList ); processSecondPasses( implicitColumnNamingSecondPassList );
processSecondPasses( setSimpleValueTypeSecondPassList ); processSecondPasses( setSimpleValueTypeSecondPassList );
processCopyIdentifierSecondPassesInOrder();
processFkSecondPassesInOrder(); processFkSecondPassesInOrder();
processSecondPasses( createKeySecondPasList ); processSecondPasses( createKeySecondPasList );
@ -1661,14 +1645,6 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
} }
} }
private void processCopyIdentifierSecondPassesInOrder() {
if ( copyIdentifierComponentSecondPasList == null ) {
return;
}
sortCopyIdentifierComponentSecondPasses();
processSecondPasses( copyIdentifierComponentSecondPasList );
}
private void processSecondPasses(ArrayList<? extends SecondPass> secondPasses) { private void processSecondPasses(ArrayList<? extends SecondPass> secondPasses) {
if ( secondPasses == null ) { if ( secondPasses == null ) {
return; return;
@ -1681,39 +1657,6 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
secondPasses.clear(); secondPasses.clear();
} }
private void sortCopyIdentifierComponentSecondPasses() {
ArrayList<CopyIdentifierComponentSecondPass> sorted =
new ArrayList<>( copyIdentifierComponentSecondPasList.size() );
Set<CopyIdentifierComponentSecondPass> toSort = new HashSet<>( copyIdentifierComponentSecondPasList );
topologicalSort( sorted, toSort );
copyIdentifierComponentSecondPasList = sorted;
}
/* naive O(n^3) topological sort */
private void topologicalSort( List<CopyIdentifierComponentSecondPass> sorted, Set<CopyIdentifierComponentSecondPass> toSort ) {
while (!toSort.isEmpty()) {
CopyIdentifierComponentSecondPass independent = null;
searchForIndependent:
for ( CopyIdentifierComponentSecondPass secondPass : toSort ) {
for ( CopyIdentifierComponentSecondPass other : toSort ) {
if (secondPass.dependentUpon( other )) {
continue searchForIndependent;
}
}
independent = secondPass;
break;
}
if (independent == null) {
throw new MappingException( "cyclic dependency in derived identities" );
}
toSort.remove( independent );
sorted.add( independent );
}
}
private void processFkSecondPassesInOrder() { private void processFkSecondPassesInOrder() {
if ( fkSecondPassList == null || fkSecondPassList.isEmpty() ) { if ( fkSecondPassList == null || fkSecondPassList.isEmpty() ) {
return; return;

View File

@ -16,8 +16,6 @@ import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure; import org.hibernate.AssertionFailure;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.boot.model.naming.Identifier; import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
import org.hibernate.boot.model.naming.ObjectNameNormalizer;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy; import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.hibernate.boot.model.relational.Database; import org.hibernate.boot.model.relational.Database;
import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.boot.spi.MetadataBuildingContext;
@ -33,7 +31,7 @@ import org.jboss.logging.Logger;
/** /**
* @author Emmanuel Bernard * @author Emmanuel Bernard
*/ */
public class CopyIdentifierComponentSecondPass implements SecondPass { public class CopyIdentifierComponentSecondPass extends FkSecondPass {
private static final Logger log = Logger.getLogger( CopyIdentifierComponentSecondPass.class ); private static final Logger log = Logger.getLogger( CopyIdentifierComponentSecondPass.class );
private final String referencedEntityName; private final String referencedEntityName;
@ -46,12 +44,25 @@ public class CopyIdentifierComponentSecondPass implements SecondPass {
String referencedEntityName, String referencedEntityName,
Ejb3JoinColumn[] joinColumns, Ejb3JoinColumn[] joinColumns,
MetadataBuildingContext buildingContext) { MetadataBuildingContext buildingContext) {
super( comp, joinColumns );
this.component = comp; this.component = comp;
this.referencedEntityName = referencedEntityName; this.referencedEntityName = referencedEntityName;
this.buildingContext = buildingContext; this.buildingContext = buildingContext;
this.joinColumns = joinColumns; this.joinColumns = joinColumns;
} }
@Override
public String getReferencedEntityName() {
return referencedEntityName;
}
@Override
public boolean isInPrimaryKey() {
// This second pass is apparently only ever used to initialize composite identifiers
return true;
}
@Override
@SuppressWarnings({ "unchecked" }) @SuppressWarnings({ "unchecked" })
public void doSecondPass(Map persistentClasses) throws MappingException { public void doSecondPass(Map persistentClasses) throws MappingException {
PersistentClass referencedPersistentClass = (PersistentClass) persistentClasses.get( referencedEntityName ); PersistentClass referencedPersistentClass = (PersistentClass) persistentClasses.get( referencedEntityName );
@ -219,8 +230,4 @@ public class CopyIdentifierComponentSecondPass implements SecondPass {
mappingColumn.setPrecision( column.getPrecision() ); mappingColumn.setPrecision( column.getPrecision() );
mappingColumn.setScale( column.getScale() ); mappingColumn.setScale( column.getScale() );
} }
public boolean dependentUpon( CopyIdentifierComponentSecondPass other ) {
return this.referencedEntityName.equals( other.component.getOwner().getEntityName() );
}
} }