Search in sources :

Example 1 with FkSecondPass

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);
        }
    }
}
Also used : FkSecondPass(org.hibernate.cfg.FkSecondPass) AnnotationException(org.hibernate.AnnotationException)

Example 2 with FkSecondPass

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;
    }
}
Also used : FkSecondPass(org.hibernate.cfg.FkSecondPass) ArrayList(java.util.ArrayList) RecoverableException(org.hibernate.cfg.RecoverableException)

Example 3 with FkSecondPass

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();
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) FkSecondPass(org.hibernate.cfg.FkSecondPass) ArrayList(java.util.ArrayList) PersistentClass(org.hibernate.mapping.PersistentClass)

Aggregations

FkSecondPass (org.hibernate.cfg.FkSecondPass)3 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 Set (java.util.Set)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1 AnnotationException (org.hibernate.AnnotationException)1 RecoverableException (org.hibernate.cfg.RecoverableException)1 PersistentClass (org.hibernate.mapping.PersistentClass)1