From 0e2069753c53fbd37ce7fc88ae44d8cb958076b7 Mon Sep 17 00:00:00 2001
From: gpawel <gpawel>
Date: Tue, 14 Feb 2012 13:46:05 +0000
Subject: [PATCH] fixing bad performance of listRelatedDataSets

SVN: 24453
---
 .../openbis/generic/server/CommonServer.java  | 23 +++++++-
 .../generic/server/dataaccess/IDataDAO.java   |  8 ++-
 .../generic/server/dataaccess/db/DataDAO.java | 57 +++++++++++++++----
 3 files changed, 72 insertions(+), 16 deletions(-)

diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
index d3063464789..39965fa5e99 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
@@ -22,10 +22,12 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Date;
+import java.util.EnumMap;
 import java.util.HashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 
 import org.springframework.dao.DataAccessException;
@@ -1025,11 +1027,30 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
             final List<? extends IEntityInformationHolder> relatedEntities)
     {
         final IDataDAO dataDAO = getDAOFactory().getDataDAO();
+        EnumMap<EntityKind, List<IEntityInformationHolder>> entities =
+                new EnumMap<EntityKind, List<IEntityInformationHolder>>(EntityKind.class);
+
         for (IEntityInformationHolder entity : relatedEntities)
         {
             if (isEntityKindRelatedWithDataSets(entity.getEntityKind()))
             {
-                List<DataPE> relatedDataSets = dataDAO.listRelatedDataSets(entity);
+                List<IEntityInformationHolder> entitiesOfGivenKind =
+                        entities.get(entity.getEntityKind());
+                if (entitiesOfGivenKind == null)
+                {
+                    entitiesOfGivenKind = new ArrayList<IEntityInformationHolder>();
+                    entities.put(entity.getEntityKind(), entitiesOfGivenKind);
+                }
+                entitiesOfGivenKind.add(entity);
+            }
+        }
+
+        for (Entry<EntityKind, List<IEntityInformationHolder>> entry : entities.entrySet())
+        {
+            if (entry.getValue() != null && entry.getValue().size() > 0)
+            {
+                List<DataPE> relatedDataSets =
+                        dataDAO.listRelatedDataSets(entry.getValue(), entry.getKey());
                 resultSet.addAll(relatedDataSets);
             }
         }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IDataDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IDataDAO.java
index 40bfe33d6a3..7189bd2c786 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IDataDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IDataDAO.java
@@ -25,6 +25,7 @@ import org.springframework.dao.DataAccessException;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolder;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetArchivingStatus;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DataStorePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DeletedDataPE;
@@ -46,12 +47,13 @@ public interface IDataDAO extends IGenericDAO<DataPE>
     public boolean hasDataSet(final SamplePE sample) throws DataAccessException;
 
     /**
-     * List the {@link DataPE} related to given <var>entity</var>.
+     * List the {@link DataPE} related to given <var>entities</var> of specified
+     * <var>entityKind</var>.
      * 
      * @returns list of {@link DataPE}s that are related to given {@link IEntityInformationHolder}.
      */
-    public List<DataPE> listRelatedDataSets(final IEntityInformationHolder entity)
-            throws DataAccessException;
+    public List<DataPE> listRelatedDataSets(final List<IEntityInformationHolder> entities,
+            EntityKind entityKind) throws DataAccessException;
 
     /**
      * List the {@link DataPE} for given <var>sample</var>.
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DataDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DataDAO.java
index 9c3480a9757..71dc6e82732 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DataDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DataDAO.java
@@ -56,6 +56,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.CodeConverter;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolder;
 import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetArchivingStatus;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.dto.ColumnNames;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DataStorePE;
@@ -110,28 +111,60 @@ final class DataDAO extends AbstractGenericEntityWithPropertiesDAO<DataPE> imple
         return count > 0;
     }
 
-    public final List<DataPE> listRelatedDataSets(final IEntityInformationHolder entity)
-            throws DataAccessException
+    public final List<DataPE> listRelatedDataSets(final List<IEntityInformationHolder> entities,
+            EntityKind entityKind) throws DataAccessException
     {
-        assert entity != null : "Unspecified entity.";
+        assert entities != null : "Unspecified entities.";
+        assert entities.size() > 0 : "Empty entities.";
+        assert entityKind != null : "Unspecified entity kind.";
 
-        final String entityName = entity.getEntityKind().toString().toLowerCase();
+        final String entityName = entityKind.toString().toLowerCase();
         final String query =
                 String.format("from %s e " + "left join fetch e.experimentInternal "
                         + "left join fetch e.sampleInternal " + "left join fetch e.parents "
                         + "left join fetch e.containedDataSets "
-                        + "left join fetch e.dataSetProperties " + "where e.%sInternal.id = ?",
-                        TABLE_NAME, entityName);
-        final List<DataPE> list = cast(getHibernateTemplate().find(query, toArray(entity.getId())));
+                        + "left join fetch e.dataSetProperties "
+                        + "where e.%sInternal.id IN (:ids)", TABLE_NAME, entityName);
 
-        // distinct does not work properly in HQL for left joins
-        distinct(list);
+        final List<Long> ids = new ArrayList<Long>();
+        for (IEntityInformationHolder entity : entities)
+        {
+            ids.add(entity.getId());
+        }
+        final List<DataPE> results = new ArrayList<DataPE>();
+        BatchOperationExecutor.executeInBatches(new IBatchOperation<Long>()
+            {
+                public void execute(List<Long> entityIds)
+                {
+
+                    final List<DataPE> list =
+                            cast(getHibernateTemplate().findByNamedParam(query, "ids", entityIds));
+                    results.addAll(list);
+                }
+
+                public List<Long> getAllEntities()
+                {
+                    return ids;
+                }
+
+                public String getEntityName()
+                {
+                    return "dataSet";
+                }
+
+                public String getOperationName()
+                {
+                    return "listRelatedDataSets";
+                }
+            });
+
+        distinct(results);
         if (operationLog.isDebugEnabled())
         {
-            operationLog.debug(String.format("%d external data have been found for [entity=%s].",
-                    list.size(), entity));
+            operationLog.debug(String.format("%d external data have been found for %d entities.",
+                    results.size(), entities.size()));
         }
-        return list;
+        return results;
     }
 
     public final List<DataPE> listDataSets(final SamplePE sample) throws DataAccessException
-- 
GitLab