Skip to content

Commit

Permalink
Merge pull request #4398 from mtbc/adjust-graph-type-query
Browse files Browse the repository at this point in the history
improve graph operation performance
  • Loading branch information
jburel committed Feb 24, 2016
2 parents 333c901 + 9b93555 commit 49d1a2b
Showing 1 changed file with 30 additions and 29 deletions.
59 changes: 30 additions & 29 deletions components/server/src/ome/services/graphs/GraphTraversal.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2014-2015 University of Dundee & Open Microscopy Environment.
* Copyright (C) 2014-2016 University of Dundee & Open Microscopy Environment.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
Expand Down Expand Up @@ -37,9 +37,9 @@
import org.slf4j.LoggerFactory;
import org.hibernate.Hibernate;
import org.hibernate.Query;
import org.hibernate.QueryException;
import org.hibernate.Session;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;

import com.google.common.base.Joiner;
import com.google.common.base.Objects;
Expand Down Expand Up @@ -77,6 +77,9 @@ public class GraphTraversal {
/* all bulk operations are batched; this size should be suitable for IN (:ids) for HQL */
private static final int BATCH_SIZE = 256;

/* the full name of the model object classes for which subclasses need not be queried */
private static final Set<String> NO_SUBCLASS_QUERY = Collections.synchronizedSet(new HashSet<String>());

/**
* A tuple noting the state of a mapped object instance in the current graph traversal.
* @author m.t.b.carroll@dundee.ac.uk
Expand Down Expand Up @@ -740,35 +743,33 @@ private Map<Long, CI> findObjectDetails(String className, Collection<Long> ids)
}

if (!idsToQuery.isEmpty()) {
/* query persisted object instances without loading them */
final String rootQuery = "FROM " + className + " WHERE id IN (:ids)";
for (final List<Long> idsBatch : Iterables.partition(idsToQuery, BATCH_SIZE)) {
final Iterator<Object> objectInstances = session.createQuery(rootQuery).setParameterList("ids", idsBatch).iterate();
while (objectInstances.hasNext()) {
/*final*/ Object objectInstance = objectInstances.next();
if (objectInstance instanceof HibernateProxy) {
/* TODO: this is an awkward hack pending Hibernate 4's type() function */
final LazyInitializer initializer = ((HibernateProxy) objectInstance).getHibernateLazyInitializer();
final Long id = (Long) initializer.getIdentifier();
String realClassName = initializer.getEntityName();
boolean lookForSubclass = true;
while (lookForSubclass) {
lookForSubclass = false;
for (final String subclassName : model.getSubclassesOf(realClassName)) {
final String classQuery = "FROM " + subclassName + " WHERE id = :id";
final Iterator<Object> instance = session.createQuery(classQuery).setParameter("id", id).iterate();
if (instance.hasNext()) {
realClassName = subclassName;
lookForSubclass = true;
break;
}
}
}
objectInstance = new CI(realClassName, id).toIObject();
boolean subclassesQueried = false;

if (!NO_SUBCLASS_QUERY.contains(className)) {
try {
/* determine the class of persisted objects without loading them */
final String rootQuery = "SELECT r.id, TYPE(r) FROM " + className + " r WHERE r.id IN (:ids)";
for (final List<Long> idsBatch : Iterables.partition(idsToQuery, BATCH_SIZE)) {
for (final Object[] result :
(List<Object[]>) session.createQuery(rootQuery).setParameterList("ids", idsBatch).list()) {
final Long id = (Long) result[0];
final Class<? extends IObject> objectClass = (Class<? extends IObject>) result[1];
final CI object = new CI(objectClass.getName(), id);
objectsById.put(object.id, object);
planning.aliases.put(new CI(className, object.id), object);
}
}
final CI object = new CI((IObject) objectInstance);
subclassesQueried = true;
} catch (QueryException e) {
NO_SUBCLASS_QUERY.add(className);
}
}
if (!subclassesQueried) {
/* the class does not have subclasses to determine */
for (final Long id : idsToQuery) {
final CI object = new CI(className, id);
objectsById.put(object.id, object);
planning.aliases.put(new CI(className, object.id), object);
planning.aliases.put(object, object);
}
}

Expand Down

0 comments on commit 49d1a2b

Please sign in to comment.