From 838b7d84fc564164e8fa7410b9c5f5ba76a540f4 Mon Sep 17 00:00:00 2001
From: gpawel <gpawel>
Date: Tue, 14 Feb 2012 11:57:15 +0000
Subject: [PATCH] LMS-2768 fixing performance of sample_relationships and
 dataset_relationships

SVN: 24448
---
 .../dataaccess/db/DatabaseVersionHolder.java  |   2 +-
 .../server/dataaccess/db/DeletionDAO.java     | 128 ++++++++++++++++++
 .../shared/dto/DataSetRelationshipPE.java     | 107 +++++++++++++++
 .../dto/DeletedSampleRelationshipPE.java      |  23 ++++
 .../shared/dto/SampleRelationshipPE.java      |  19 +++
 .../shared/translator/DataSetTranslator.java  |   3 +
 openbis/source/java/hibernateContext.xml      |   4 +-
 7 files changed, 283 insertions(+), 3 deletions(-)
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataSetRelationshipPE.java

diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DatabaseVersionHolder.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DatabaseVersionHolder.java
index e0b79c6048b..59a7e5f6953 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DatabaseVersionHolder.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DatabaseVersionHolder.java
@@ -24,7 +24,7 @@ package ch.systemsx.cisd.openbis.generic.server.dataaccess.db;
 public final class DatabaseVersionHolder
 {
     /** Current version of the database. */
-    private static final String DATABASE_VERSION = "097"; // S125
+    private static final String DATABASE_VERSION = "098"; // S125
 
     private DatabaseVersionHolder()
     {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DeletionDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DeletionDAO.java
index b70533e81ef..75a166640ab 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DeletionDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/DeletionDAO.java
@@ -47,6 +47,8 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.TechId;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DatabaseInstancePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.DeletionPE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.IDeletablePE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.SampleRelationshipPE;
+import ch.systemsx.cisd.openbis.generic.shared.dto.TableNames;
 import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.util.HibernateUtils;
 
@@ -159,11 +161,46 @@ final class DeletionDAO extends AbstractGenericEntityDAO<DeletionPE> implements
 
             });
 
+        switch (entityKind)
+        {
+            case SAMPLE:
+                revertDeletionOfRelationships(deletion, TableNames.SAMPLE_RELATIONSHIPS_ALL_TABLE);
+                break;
+            case DATA_SET:
+                revertDeletionOfRelationships(deletion, TableNames.DATA_SET_RELATIONSHIPS_ALL_TABLE);
+                break;
+            case EXPERIMENT:
+                break;
+            case MATERIAL:
+                break;
+        }
+
         scheduleDynamicPropertiesEvaluationByIds(TechId.asLongs(ids), entityKind);
 
         operationLog.info(String.format("%s %s(s) reverted", updatedRows, entityKind.name()));
     }
 
+    private void revertDeletionOfRelationships(final DeletionPE deletion, final String tableName)
+    {
+        assert deletion != null : "Unspecified deletion";
+
+        int updatedRows = (Integer) executeStatelessAction(new StatelessHibernateCallback()
+            {
+
+                public Object doInStatelessSession(StatelessSession session)
+                {
+                    String query =
+                            String.format("UPDATE %s SET del_id = NULL WHERE del_id = :deletionId",
+                                    tableName);
+                    final SQLQuery sqlQuery = session.createSQLQuery(query);
+                    sqlQuery.setParameter("deletionId", HibernateUtils.getId(deletion));
+                    return sqlQuery.executeUpdate();
+                }
+            });
+
+        operationLog.info(String.format("%s %s(s) reverted", updatedRows, tableName));
+    }
+
     public List<TechId> findTrashedSampleIds(final List<TechId> deletionIds)
     {
         return findTrashedEntityIds(deletionIds, EntityKind.SAMPLE);
@@ -254,6 +291,21 @@ final class DeletionDAO extends AbstractGenericEntityDAO<DeletionPE> implements
                             .setParameterList("ids", TechId.asLongs(entityIds)).executeUpdate();
                 }
             });
+
+        switch (entityKind)
+        {
+            case SAMPLE:
+                trashSampleRelationships(entityIds, deletion);
+                break;
+            case DATA_SET:
+                trashDataSetRelationships(entityIds, deletion);
+                break;
+            case EXPERIMENT:
+                break;
+            case MATERIAL:
+                break;
+        }
+
         if (operationLog.isInfoEnabled())
         {
             operationLog.info(String.format("trashing %d %ss", updatedRows, entityKind.getLabel()));
@@ -266,6 +318,82 @@ final class DeletionDAO extends AbstractGenericEntityDAO<DeletionPE> implements
         return updatedRows;
     }
 
+    public int trashSampleRelationships(final List<TechId> samplesIds, final DeletionPE deletion)
+            throws DataAccessException
+    {
+        if (samplesIds.isEmpty())
+        {
+            return 0;
+        }
+        final HibernateTemplate hibernateTemplate = getHibernateTemplate();
+        int updatedRows = (Integer) hibernateTemplate.execute(new HibernateCallback()
+            {
+                //
+                // HibernateCallback
+                //
+                public final Object doInHibernate(final Session session) throws HibernateException,
+                        SQLException
+                {
+                    // NOTE: 'VERSIONED' makes modification time modified too
+                    return session
+                            .createQuery(
+                                    "UPDATE "
+                                            + SampleRelationshipPE.class.getSimpleName()
+                                            + " SET deletion = :deletion"
+                                            + " WHERE deletion IS NULL"
+                                            + " AND (parentSample.id IN (:ids) OR childSample.id in (:ids))")
+                            .setParameter("deletion", deletion)
+                            .setParameterList("ids", TechId.asLongs(samplesIds)).executeUpdate();
+                }
+            });
+        if (operationLog.isInfoEnabled())
+        {
+            operationLog.info(String
+                    .format("trashing %d %ss", updatedRows, "sample relationships."));
+        }
+        hibernateTemplate.flush();
+
+        return updatedRows;
+    }
+
+    public int trashDataSetRelationships(final List<TechId> dataSetIds, final DeletionPE deletion)
+            throws DataAccessException
+    {
+        if (dataSetIds.isEmpty())
+        {
+            return 0;
+        }
+        final HibernateTemplate hibernateTemplate = getHibernateTemplate();
+        int updatedRows = (Integer) hibernateTemplate.execute(new HibernateCallback()
+            {
+                //
+                // HibernateCallback
+                //
+                public final Object doInHibernate(final Session session) throws HibernateException,
+                        SQLException
+                {
+                    // NOTE: 'VERSIONED' makes modification time modified too
+                    return session
+                            .createQuery(
+                                    "UPDATE "
+                                            + SampleRelationshipPE.class.getSimpleName()
+                                            + " SET deletion = :deletion"
+                                            + " WHERE deletion IS NULL"
+                                            + " AND (parentDataSet.id IN (:ids) OR childDataSet.id in (:ids))")
+                            .setParameter("deletion", deletion)
+                            .setParameterList("ids", TechId.asLongs(dataSetIds)).executeUpdate();
+                }
+            });
+        if (operationLog.isInfoEnabled())
+        {
+            operationLog.info(String.format("trashing %d %ss", updatedRows,
+                    "data set relationships."));
+        }
+        hibernateTemplate.flush();
+
+        return updatedRows;
+    }
+
     public List<DeletionPE> findAllById(List<Long> ids)
     {
         if (ids.isEmpty())
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataSetRelationshipPE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataSetRelationshipPE.java
new file mode 100644
index 00000000000..76f1d092d13
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DataSetRelationshipPE.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2010 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.generic.shared.dto;
+
+import java.io.Serializable;
+
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+import org.hibernate.validator.NotNull;
+
+import ch.systemsx.cisd.openbis.generic.shared.IServer;
+
+/**
+ * <i>Persistent Entity</i> object representing data set relationship.
+ * 
+ * @author Pawel Glyzewski
+ */
+@Entity
+@Table(name = TableNames.DATA_SET_RELATIONSHIPS_VIEW, uniqueConstraints = @UniqueConstraint(columnNames =
+    { ColumnNames.DATA_PARENT_COLUMN, ColumnNames.DATA_CHILD_COLUMN }))
+public class DataSetRelationshipPE implements Serializable
+{
+    private static final long serialVersionUID = IServer.VERSION;
+
+    private DataPE parentDataSet;
+
+    private DataPE childDataSet;
+
+    /**
+     * Deletion information.
+     * <p>
+     * If not <code>null</code>, then this data set is considered <i>deleted</i> (moved to trash).
+     * </p>
+     */
+    private DeletionPE deletion;
+
+    @Deprecated
+    public DataSetRelationshipPE()
+    {
+    }
+
+    public DataSetRelationshipPE(DataPE parentDataSet, DataPE childDataSet)
+    {
+        this.parentDataSet = parentDataSet;
+        this.childDataSet = childDataSet;
+    }
+
+    @NotNull(message = ValidationMessages.PARENT_NOT_NULL_MESSAGE)
+    @ManyToOne(fetch = FetchType.EAGER)
+    @JoinColumn(name = ColumnNames.DATA_PARENT_COLUMN)
+    @Id
+    public DataPE getParentDataSet()
+    {
+        return parentDataSet;
+    }
+
+    public void setParentDataSet(DataPE parentDataSet)
+    {
+        this.parentDataSet = parentDataSet;
+    }
+
+    @NotNull(message = ValidationMessages.CHILD_NOT_NULL_MESSAGE)
+    @ManyToOne(fetch = FetchType.EAGER)
+    @JoinColumn(name = ColumnNames.DATA_CHILD_COLUMN)
+    @Id
+    public DataPE getChildDataSet()
+    {
+        return childDataSet;
+    }
+
+    public void setChildDataSet(DataPE childDataSet)
+    {
+        this.childDataSet = childDataSet;
+    }
+
+    @ManyToOne(fetch = FetchType.EAGER)
+    @JoinColumn(name = ColumnNames.DELETION_COLUMN)
+    public DeletionPE getDeletion()
+    {
+        return deletion;
+    }
+
+    public void setDeletion(final DeletionPE deletion)
+    {
+        this.deletion = deletion;
+    }
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DeletedSampleRelationshipPE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DeletedSampleRelationshipPE.java
index d003243ac93..9ce620438db 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DeletedSampleRelationshipPE.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DeletedSampleRelationshipPE.java
@@ -18,9 +18,12 @@ package ch.systemsx.cisd.openbis.generic.shared.dto;
 
 import javax.persistence.Column;
 import javax.persistence.Entity;
+import javax.persistence.FetchType;
 import javax.persistence.GeneratedValue;
 import javax.persistence.GenerationType;
 import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
 import javax.persistence.SequenceGenerator;
 import javax.persistence.Table;
 
@@ -42,6 +45,14 @@ public class DeletedSampleRelationshipPE
 
     private Long parentId;
 
+    /**
+     * Deletion information.
+     * <p>
+     * If not <code>null</code>, then this data set is considered <i>deleted</i> (moved to trash).
+     * </p>
+     */
+    private DeletionPE deletion;
+
     @Id
     @SequenceGenerator(name = SequenceNames.SAMPLE_SEQUENCE, sequenceName = SequenceNames.SAMPLE_SEQUENCE, allocationSize = 1)
     @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = SequenceNames.SAMPLE_SEQUENCE)
@@ -66,4 +77,16 @@ public class DeletedSampleRelationshipPE
     {
         this.parentId = parentId;
     }
+
+    @ManyToOne(fetch = FetchType.EAGER)
+    @JoinColumn(name = ColumnNames.DELETION_COLUMN)
+    public DeletionPE getDeletion()
+    {
+        return deletion;
+    }
+
+    public void setDeletion(final DeletionPE deletion)
+    {
+        this.deletion = deletion;
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SampleRelationshipPE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SampleRelationshipPE.java
index eed7562e204..9ed337a498d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SampleRelationshipPE.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SampleRelationshipPE.java
@@ -54,6 +54,14 @@ public class SampleRelationshipPE implements Serializable
 
     private RelationshipTypePE relationship;
 
+    /**
+     * Deletion information.
+     * <p>
+     * If not <code>null</code>, then this data set is considered <i>deleted</i> (moved to trash).
+     * </p>
+     */
+    private DeletionPE deletion;
+
     @Deprecated
     public SampleRelationshipPE()
     {
@@ -121,4 +129,15 @@ public class SampleRelationshipPE implements Serializable
         this.id = id;
     }
 
+    @ManyToOne(fetch = FetchType.EAGER)
+    @JoinColumn(name = ColumnNames.DELETION_COLUMN)
+    public DeletionPE getDeletion()
+    {
+        return deletion;
+    }
+
+    public void setDeletion(final DeletionPE deletion)
+    {
+        this.deletion = deletion;
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/DataSetTranslator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/DataSetTranslator.java
index bbf9df2d7f5..4dd70b494ba 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/DataSetTranslator.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/DataSetTranslator.java
@@ -142,6 +142,7 @@ public class DataSetTranslator
     public static ExternalData translate(DataPE dataPE, String baseIndexURL, boolean withDetails,
             final LoadableFields... withExperimentFields)
     {
+        long start = System.currentTimeMillis();
         ExternalData externalData = null;
         if (dataPE.isContainer())
         {
@@ -184,6 +185,8 @@ public class DataSetTranslator
         externalData.setExperiment(ExperimentTranslator.translate(experiment, baseIndexURL,
                 withExperimentFields));
         externalData.setDeletion(DeletionTranslator.translate(dataPE.getDeletion()));
+        long end = System.currentTimeMillis();
+        System.out.println("CCCCCCCCCCCCCCCC: " + (end - start));
         return externalData;
     }
 
diff --git a/openbis/source/java/hibernateContext.xml b/openbis/source/java/hibernateContext.xml
index cca7c8ee042..11a2d3c0a5c 100644
--- a/openbis/source/java/hibernateContext.xml
+++ b/openbis/source/java/hibernateContext.xml
@@ -91,6 +91,7 @@
                 <value>ch.systemsx.cisd.openbis.generic.shared.dto.DeletedSamplePE</value>
                 <value>ch.systemsx.cisd.openbis.generic.shared.dto.DeletedSampleRelationshipPE</value>
                 <value>ch.systemsx.cisd.openbis.generic.shared.dto.CorePluginPE</value>
+                <value>ch.systemsx.cisd.openbis.generic.shared.dto.DataSetRelationshipPE</value>
                 <value>ch.systemsx.cisd.openbis.generic.shared.dto.PostRegistrationPE</value>
 
             </list>
@@ -125,8 +126,7 @@
                 <!--  Uncomment this for debugging the Hibernate sql queries
 <prop key="hibernate.show_sql">true</prop>
 <prop key="hibernate.use_sql_comments">true</prop>
-<prop key="hibernate.format_sql">true</prop> 
-                  -->
+<prop key="hibernate.format_sql">true</prop> -->
 
             </props>
         </property>
-- 
GitLab