use of org.hibernate.cfg.FkSecondPass in project hibernate-orm by hibernate.
the class InFlightMetadataCollectorImpl method buildRecursiveOrderedFkSecondPasses.
/**
* Recursively builds a list of FkSecondPass instances ready to be processed in this order.
* Checking all dependencies recursively seems quite expensive, but the original code just relied
* on some sort of table name sorting which failed in certain circumstances.
* <p/>
* See <tt>ANN-722</tt> and <tt>ANN-730</tt>
*
* @param orderedFkSecondPasses The list containing the <code>FkSecondPass<code> instances ready
* for processing.
* @param isADependencyOf Our lookup data structure to determine dependencies between tables
* @param startTable Table name to start recursive algorithm.
* @param currentTable The current table name used to check for 'new' dependencies.
*/
private void buildRecursiveOrderedFkSecondPasses(List<FkSecondPass> orderedFkSecondPasses, Map<String, Set<FkSecondPass>> isADependencyOf, String startTable, String currentTable) {
Set<FkSecondPass> dependencies = isADependencyOf.get(currentTable);
// bottom out
if (dependencies == null || dependencies.size() == 0) {
return;
}
for (FkSecondPass sp : dependencies) {
String dependentTable = sp.getValue().getTable().getQualifiedTableName().render();
if (dependentTable.compareTo(startTable) == 0) {
throw new AnnotationException("Foreign key circularity dependency involving the following tables: " + startTable + ", " + dependentTable);
}
buildRecursiveOrderedFkSecondPasses(orderedFkSecondPasses, isADependencyOf, startTable, dependentTable);
if (!orderedFkSecondPasses.contains(sp)) {
orderedFkSecondPasses.add(0, sp);
}
}
}
use of org.hibernate.cfg.FkSecondPass in project hibernate-orm by hibernate.
the class InFlightMetadataCollectorImpl method processEndOfQueue.
private void processEndOfQueue(List<FkSecondPass> endOfQueueFkSecondPasses) {
/*
* If a second pass raises a recoverableException, queue it for next round
* stop of no pass has to be processed or if the number of pass to processes
* does not diminish between two rounds.
* If some failing pass remain, raise the original exception
*/
boolean stopProcess = false;
RuntimeException originalException = null;
while (!stopProcess) {
List<FkSecondPass> failingSecondPasses = new ArrayList<>();
for (FkSecondPass pass : endOfQueueFkSecondPasses) {
try {
pass.doSecondPass(getEntityBindingMap());
} catch (RecoverableException e) {
failingSecondPasses.add(pass);
if (originalException == null) {
originalException = (RuntimeException) e.getCause();
}
}
}
stopProcess = failingSecondPasses.size() == 0 || failingSecondPasses.size() == endOfQueueFkSecondPasses.size();
endOfQueueFkSecondPasses = failingSecondPasses;
}
if (endOfQueueFkSecondPasses.size() > 0) {
throw originalException;
}
}
use of org.hibernate.cfg.FkSecondPass in project hibernate-orm by hibernate.
the class InFlightMetadataCollectorImpl method processFkSecondPassesInOrder.
private void processFkSecondPassesInOrder() {
if (fkSecondPassList == null || fkSecondPassList.isEmpty()) {
return;
}
// split FkSecondPass instances into primary key and non primary key FKs.
// While doing so build a map of class names to FkSecondPass instances depending on this class.
Map<String, Set<FkSecondPass>> isADependencyOf = new HashMap<>();
List<FkSecondPass> endOfQueueFkSecondPasses = new ArrayList<>(fkSecondPassList.size());
for (FkSecondPass sp : fkSecondPassList) {
if (sp.isInPrimaryKey()) {
final String referenceEntityName = sp.getReferencedEntityName();
final PersistentClass classMapping = getEntityBinding(referenceEntityName);
final String dependentTable = classMapping.getTable().getQualifiedTableName().render();
if (!isADependencyOf.containsKey(dependentTable)) {
isADependencyOf.put(dependentTable, new HashSet<>());
}
isADependencyOf.get(dependentTable).add(sp);
} else {
endOfQueueFkSecondPasses.add(sp);
}
}
// using the isADependencyOf map we order the FkSecondPass recursively instances into the right order for processing
List<FkSecondPass> orderedFkSecondPasses = new ArrayList<>(fkSecondPassList.size());
for (String tableName : isADependencyOf.keySet()) {
buildRecursiveOrderedFkSecondPasses(orderedFkSecondPasses, isADependencyOf, tableName, tableName);
}
// process the ordered FkSecondPasses
for (FkSecondPass sp : orderedFkSecondPasses) {
sp.doSecondPass(getEntityBindingMap());
}
processEndOfQueue(endOfQueueFkSecondPasses);
fkSecondPassList.clear();
}
Aggregations