From d71294dd89a8bee02fc800593013092a3c2302ab Mon Sep 17 00:00:00 2001 From: buczekp <buczekp> Date: Mon, 18 Jul 2011 13:33:08 +0000 Subject: [PATCH] [LMS-2364] implemented cascade deletion (no tests yet) SVN: 22175 --- .../bo/AbstractSampleBusinessObject.java | 2 +- .../server/business/bo/DataSetTable.java | 6 +- .../server/business/bo/ExperimentBO.java | 10 +- .../server/business/bo/IDataSetTable.java | 9 +- .../server/business/bo/IExperimentBO.java | 2 +- .../server/business/bo/ISampleTable.java | 2 +- .../generic/server/business/bo/ITrashBO.java | 3 +- .../server/business/bo/SampleTable.java | 10 +- .../generic/server/business/bo/TrashBO.java | 49 ++++++++- .../generic/server/dataaccess/IDataDAO.java | 12 +- .../server/dataaccess/IExperimentDAO.java | 2 +- .../generic/server/dataaccess/ISampleDAO.java | 24 ++-- .../generic/server/dataaccess/db/DataDAO.java | 67 ++++++++++-- .../server/dataaccess/db/ExperimentDAO.java | 44 ++++++-- .../server/dataaccess/db/SampleDAO.java | 103 ++++++++++++++++-- .../GenericDataSetTypeSlaveServerPlugin.java | 3 +- 16 files changed, 278 insertions(+), 70 deletions(-) diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractSampleBusinessObject.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractSampleBusinessObject.java index 10a25de603e..9949b4a7703 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractSampleBusinessObject.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/AbstractSampleBusinessObject.java @@ -546,7 +546,7 @@ abstract class AbstractSampleBusinessObject extends AbstractSampleIdentifierBusi sample.getIdentifier(), parentToAdd.getIdentifier()); } else { - final Set<TechId> nextToVisit = getSampleDAO().listParents(toVisit, relationship); + final Set<TechId> nextToVisit = getSampleDAO().listSampleIdsByChildrenIds(toVisit, relationship); visited.addAll(toVisit); nextToVisit.removeAll(visited); toVisit = nextToVisit; diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataSetTable.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataSetTable.java index 170707cc51d..4c73d12f65e 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataSetTable.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataSetTable.java @@ -235,15 +235,17 @@ public final class DataSetTable extends AbstractDataSetBusinessObject implements dataSets.addAll(getDataDAO().listDataSets(experiment)); } - public void trashLoadedDataSets(DeletionPE deletion) + public int trashByTechIds(List<TechId> dataSetIds, DeletionPE deletion) + throws UserFailureException { try { - getDataDAO().trash(dataSets, deletion); + return getDataDAO().trash(dataSetIds, deletion); } catch (final DataAccessException ex) { throwException(ex, "Data Set", EntityKind.DATA_SET); } + return -1; // not possible } public void deleteLoadedDataSets(String reason) diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExperimentBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExperimentBO.java index 3a4d955105c..20348f239ed 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExperimentBO.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ExperimentBO.java @@ -39,6 +39,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewExperiment; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.api.IManagedProperty; import ch.systemsx.cisd.openbis.generic.shared.dto.AttachmentPE; import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE; +import ch.systemsx.cisd.openbis.generic.shared.dto.DeletionPE; import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePE; import ch.systemsx.cisd.openbis.generic.shared.dto.EventPE; import ch.systemsx.cisd.openbis.generic.shared.dto.EventPE.EntityType; @@ -47,7 +48,6 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE; import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPropertyPE; import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentTypePE; import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentUpdatesDTO; -import ch.systemsx.cisd.openbis.generic.shared.dto.DeletionPE; import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE; import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE; import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE; @@ -208,19 +208,17 @@ public final class ExperimentBO extends AbstractBusinessObject implements IExper + "') not found in experiment '" + experiment.getIdentifier() + "'."); } - public void trashByTechIds(List<TechId> experimentIds, DeletionPE deletion) + public int trashByTechIds(List<TechId> experimentIds, DeletionPE deletion) throws UserFailureException { try { - getSessionFactory().getCurrentSession().flush(); - getSessionFactory().getCurrentSession().clear(); - - getExperimentDAO().trash(experimentIds, deletion); + return getExperimentDAO().trash(experimentIds, deletion); } catch (final DataAccessException ex) { throwException(ex, "Experiment", EntityKind.EXPERIMENT); } + return -1; // not possible } public void deleteByTechIds(List<TechId> experimentIds, String reason) diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IDataSetTable.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IDataSetTable.java index 270b74eb5b4..d3bb6d8ffc3 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IDataSetTable.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IDataSetTable.java @@ -19,6 +19,7 @@ package ch.systemsx.cisd.openbis.generic.server.business.bo; import java.util.List; import java.util.Map; +import ch.systemsx.cisd.common.exceptions.UserFailureException; import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.LinkModel; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewDataSet; @@ -70,9 +71,13 @@ public interface IDataSetTable void setDataSets(List<DataPE> dataSets); /** - * Moves loaded data sets to trash for specified reason. + * Moves data sets to trash with given deletion. + * + * @param dataSetIds data set technical identifiers + * @throws UserFailureException if one of the data sets can not be moved to trash. */ - void trashLoadedDataSets(DeletionPE deletion); + public int trashByTechIds(List<TechId> dataSetIds, DeletionPE deletion) + throws UserFailureException; /** * Permanently Deletes loaded data sets for specified reason. diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IExperimentBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IExperimentBO.java index 668340e2f37..6d4512b9211 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IExperimentBO.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/IExperimentBO.java @@ -89,7 +89,7 @@ public interface IExperimentBO extends IEntityBusinessObject * @param experimentIds experiment technical identifiers * @throws UserFailureException if one of the experiments can not be moved to trash. */ - void trashByTechIds(List<TechId> experimentIds, DeletionPE deletion); + int trashByTechIds(List<TechId> experimentIds, DeletionPE deletion); /** * Changes the value of a managed property. diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ISampleTable.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ISampleTable.java index 68a1b38f937..1fa3e8fcc17 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ISampleTable.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ISampleTable.java @@ -78,7 +78,7 @@ public interface ISampleTable * @param sampleIds sample technical identifiers * @throws UserFailureException if one of the samples can not be moved to trash. */ - public void trashByTechIds(List<TechId> sampleIds, DeletionPE deletion) + public int trashByTechIds(List<TechId> sampleIds, DeletionPE deletion) throws UserFailureException; } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ITrashBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ITrashBO.java index e155d2689de..300a60a559c 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ITrashBO.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/ITrashBO.java @@ -19,7 +19,6 @@ package ch.systemsx.cisd.openbis.generic.server.business.bo; import java.util.List; import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; -import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE; /** * Handles the trash of entities. @@ -34,7 +33,7 @@ public interface ITrashBO public void trashExperiments(List<TechId> experimentIds); - public void trashDataSets(List<DataPE> dataSets); + public void trashDataSets(List<TechId> dataSetIds); /** Puts back all entities moved to trash in deletion with specified id. */ public void revertDeletion(TechId deletionId); diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleTable.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleTable.java index 5c2f74eb540..5942b4b7f07 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleTable.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/SampleTable.java @@ -31,10 +31,10 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityProperty; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleBatchUpdateDetails; +import ch.systemsx.cisd.openbis.generic.shared.dto.DeletionPE; import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePE; import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePropertyTypePE; import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE; -import ch.systemsx.cisd.openbis.generic.shared.dto.DeletionPE; import ch.systemsx.cisd.openbis.generic.shared.dto.ListSamplesByPropertyCriteria; import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE; import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE; @@ -341,19 +341,17 @@ public final class SampleTable extends AbstractSampleBusinessObject implements I } } - public void trashByTechIds(List<TechId> sampleIds, DeletionPE deletion) + public int trashByTechIds(List<TechId> sampleIds, DeletionPE deletion) throws UserFailureException { try { - getSessionFactory().getCurrentSession().flush(); - getSessionFactory().getCurrentSession().clear(); - - getSampleDAO().trash(sampleIds, deletion); + return getSampleDAO().trash(sampleIds, deletion); } catch (final DataAccessException ex) { throwException(ex, "Sample", EntityKind.SAMPLE); } + return -1; // not possible } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/TrashBO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/TrashBO.java index 8132222cf56..de43071759f 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/TrashBO.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/TrashBO.java @@ -16,13 +16,15 @@ package ch.systemsx.cisd.openbis.generic.server.business.bo; +import java.util.ArrayList; import java.util.List; import org.springframework.dao.DataAccessException; import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory; +import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDataDAO; +import ch.systemsx.cisd.openbis.generic.server.dataaccess.ISampleDAO; import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; -import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE; import ch.systemsx.cisd.openbis.generic.shared.dto.DeletionPE; import ch.systemsx.cisd.openbis.generic.shared.dto.Session; @@ -60,22 +62,57 @@ public class TrashBO extends AbstractBusinessObject implements ITrashBO { assert deletion != null; ISampleTable sampleTableBO = boFactory.createSampleTable(session); - sampleTableBO.trashByTechIds(sampleIds, deletion); + int trashedCount = sampleTableBO.trashByTechIds(sampleIds, deletion); + if (trashedCount > 0) + { + trashSampleDependentChildrenAndComponents(sampleIds); + trashSampleDependentDataSets(sampleIds); + } } public void trashExperiments(List<TechId> experimentIds) { assert deletion != null; IExperimentBO experimentBO = boFactory.createExperimentBO(session); - experimentBO.trashByTechIds(experimentIds, deletion); + int trashedCount = experimentBO.trashByTechIds(experimentIds, deletion); + if (trashedCount > 0) + { + trashExperimentDependentDataSets(experimentIds); + trashExperimentDependentSamples(experimentIds); + } } - public void trashDataSets(List<DataPE> dataSets) + public void trashDataSets(List<TechId> dataSetIds) { assert deletion != null; IDataSetTable dataSetTable = boFactory.createDataSetTable(session); - dataSetTable.setDataSets(dataSets); - dataSetTable.trashLoadedDataSets(deletion); + dataSetTable.trashByTechIds(dataSetIds, deletion); + // NOTE: data set children are not cascade trashed - a conscious decision made by Tomek + } + + private void trashSampleDependentChildrenAndComponents(List<TechId> sampleIds) + { + ISampleDAO sampleDAO = getSampleDAO(); + trashSamples(new ArrayList<TechId>(sampleDAO.listSampleIdsByParentIds(sampleIds))); + trashSamples(sampleDAO.listSampleIdsByContainerIds(sampleIds)); + } + + private void trashSampleDependentDataSets(List<TechId> sampleIds) + { + IDataDAO dataDAO = getDataDAO(); + trashDataSets(dataDAO.listDataSetIdsBySampleIds(sampleIds)); + } + + private void trashExperimentDependentSamples(List<TechId> experimentIds) + { + ISampleDAO sampleDAO = getSampleDAO(); + trashSamples(sampleDAO.listSampleIdsByExperimentIds(experimentIds)); + } + + private void trashExperimentDependentDataSets(List<TechId> experimentIds) + { + IDataDAO dataDAO = getDataDAO(); + trashDataSets(dataDAO.listDataSetIdsByExperimentIds(experimentIds)); } public void revertDeletion(TechId deletionId) 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 67fb17eb21e..d79f4e2a933 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 @@ -120,9 +120,13 @@ public interface IDataDAO extends IGenericDAO<DataPE> public void updateDataSets(List<DataPE> externalData); - /** - * Move given data sets to trash using specified deletion. - */ - public void trash(List<DataPE> dataSets, DeletionPE deletion) throws DataAccessException; + /** Move given data sets to trash using specified deletion. */ + public int trash(List<TechId> dataSetIds, DeletionPE deletion) throws DataAccessException; + + /** Returns ids of data sets connected with samples specified by given ids. */ + public List<TechId> listDataSetIdsBySampleIds(final Collection<TechId> samples); + + /** Returns ids of data sets connected with experiments specified by given ids. */ + public List<TechId> listDataSetIdsByExperimentIds(final Collection<TechId> samples); } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IExperimentDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IExperimentDAO.java index 8a52959b90e..924057cf6fe 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IExperimentDAO.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IExperimentDAO.java @@ -110,6 +110,6 @@ public interface IExperimentDAO extends IGenericDAO<ExperimentPE> /** * Move experiments with given ids to trash using specified deletion. */ - public void trash(List<TechId> experimentIds, DeletionPE deletion); + public int trash(List<TechId> experimentIds, DeletionPE deletion); } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/ISampleDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/ISampleDAO.java index b136bfeafa3..bb35bce7217 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/ISampleDAO.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/ISampleDAO.java @@ -93,16 +93,25 @@ public interface ISampleDAO extends IGenericDAO<SamplePE> List<SamplePE> listSamplesByGeneratedFrom(final SamplePE sample) throws DataAccessException; /** - * @return Unique set of ids of parents of data sets specified by ids. - * <p> - * NOTE: does not check if specified ids are proper data set ids. + * Returns ids of parents of samples specified by given ids and connected by chosen relationship + * type. */ + public Set<TechId> listSampleIdsByChildrenIds(Collection<TechId> children, TechId relationship); /** - * Returns ids of parents of samples specified by given ids and connected by chosen relationship - * type. + * Returns ids of children of samples specified by given ids. + * <p> + * NOTES: + * <li>we don't use relationship type as don't really support different relationship types + * <li>we need a set as the connection is many-to-many and we want unique ids */ - public Set<TechId> listParents(Collection<TechId> children, TechId relationship); + public Set<TechId> listSampleIdsByParentIds(Collection<TechId> parentIds); + + /** Returns ids of components of samples specified by given ids. */ + public List<TechId> listSampleIdsByContainerIds(Collection<TechId> containerIds); + + /** Returns ids of samples connected with experiments specified by given ids. */ + List<TechId> listSampleIdsByExperimentIds(Collection<TechId> experimentIds); /** * Lists samples (with minimal additional information) belonging to the given <code>space</code> @@ -126,5 +135,6 @@ public interface ISampleDAO extends IGenericDAO<SamplePE> /** * Move samples with given ids to trash using specified deletion. */ - void trash(List<TechId> sampleIds, DeletionPE deletion) throws DataAccessException; + int trash(List<TechId> sampleIds, DeletionPE deletion) throws DataAccessException; + } 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 8eb96cea930..650a1753641 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 @@ -464,18 +464,40 @@ final class DataDAO extends AbstractGenericEntityWithPropertiesDAO<DataPE> imple super.delete(entity); } - public void trash(List<DataPE> dataSets, DeletionPE deletion) throws DataAccessException + public int trash(final List<TechId> dataSetIds, final DeletionPE deletion) + throws DataAccessException { - // TODO 2011-06-16, Piotr Buczek: could be done faster with bulk update - for (DataPE dataSet : dataSets) + if (dataSetIds.isEmpty()) { - if (dataSet.getDeletion() == null) - { - dataSet.setDeletion(deletion); - } + return 0; } + final HibernateTemplate hibernateTemplate = getHibernateTemplate(); + int updatedRows = (Integer) hibernateTemplate.execute(new HibernateCallback() + { + + // + // HibernateCallback + // - getHibernateTemplate().flush(); + public final Object doInHibernate(final Session session) throws HibernateException, + SQLException + { + // NOTE: 'VERSIONED' makes modification time modified too + return session + .createQuery( + "UPDATE VERSIONED " + + DataPE.class.getSimpleName() + + " SET deletion = :deletion WHERE deletion IS NULL AND id IN (:ids) ") + .setParameter("deletion", deletion) + .setParameterList("ids", TechId.asLongs(dataSetIds)).executeUpdate(); + } + }); + if (operationLog.isInfoEnabled()) + { + operationLog.info(String.format("trashing %d data sets", updatedRows)); + } + hibernateTemplate.flush(); + return updatedRows; } @SuppressWarnings("unchecked") @@ -556,4 +578,33 @@ final class DataDAO extends AbstractGenericEntityWithPropertiesDAO<DataPE> imple scheduleDynamicPropertiesEvaluation(Arrays.asList(entity)); } + public List<TechId> listDataSetIdsBySampleIds(final Collection<TechId> samples) + { + final DetachedCriteria criteria = DetachedCriteria.forClass(DataPE.class); + final List<Long> longIds = TechId.asLongs(samples); + criteria.setProjection(Projections.id()); + criteria.add(Restrictions.in("sampleInternal.id", longIds)); + final List<Long> results = cast(getHibernateTemplate().findByCriteria(criteria)); + if (operationLog.isDebugEnabled()) + { + operationLog.info(String.format("found %s data sets for given samples", results.size())); + } + return transformNumbers2TechIdList(results); + } + + public List<TechId> listDataSetIdsByExperimentIds(final Collection<TechId> experiments) + { + final DetachedCriteria criteria = DetachedCriteria.forClass(DataPE.class); + final List<Long> longIds = TechId.asLongs(experiments); + criteria.setProjection(Projections.id()); + criteria.add(Restrictions.in("experimentInternal.id", longIds)); + final List<Long> results = cast(getHibernateTemplate().findByCriteria(criteria)); + if (operationLog.isDebugEnabled()) + { + operationLog + .info(String.format("found %s data sets for given experiments", results.size())); + } + return transformNumbers2TechIdList(results); + } + } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExperimentDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExperimentDAO.java index 98d6a1632c9..756de7db266 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExperimentDAO.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExperimentDAO.java @@ -16,6 +16,7 @@ package ch.systemsx.cisd.openbis.generic.server.dataaccess.db; +import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -25,9 +26,12 @@ import java.util.Set; import org.apache.log4j.Logger; import org.hibernate.Criteria; import org.hibernate.FetchMode; +import org.hibernate.HibernateException; +import org.hibernate.Session; import org.hibernate.criterion.DetachedCriteria; import org.hibernate.criterion.Restrictions; import org.springframework.dao.DataAccessException; +import org.springframework.orm.hibernate3.HibernateCallback; import org.springframework.orm.hibernate3.HibernateTemplate; import ch.systemsx.cisd.common.logging.LogCategory; @@ -38,10 +42,10 @@ import ch.systemsx.cisd.openbis.generic.server.dataaccess.PersistencyResources; import ch.systemsx.cisd.openbis.generic.shared.basic.CodeConverter; 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.ExperimentPE; import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPropertyPE; import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentTypePE; -import ch.systemsx.cisd.openbis.generic.shared.dto.DeletionPE; import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE; import ch.systemsx.cisd.openbis.generic.shared.dto.SpacePE; @@ -300,20 +304,40 @@ public class ExperimentDAO extends AbstractGenericEntityWithPropertiesDAO<Experi } } - public void trash(final List<TechId> experimentIds, final DeletionPE deletion) + public int trash(final List<TechId> experimentIds, final DeletionPE deletion) throws DataAccessException { - // TODO 2011-06-16, Piotr Buczek: could be done faster with bulk update - for (TechId experimentId : experimentIds) + if (experimentIds.isEmpty()) { - ExperimentPE experiment = loadByTechId(experimentId); - if (experiment.getDeletion() == null) - { - experiment.setDeletion(deletion); - } + return 0; } + final HibernateTemplate hibernateTemplate = getHibernateTemplate(); + int updatedRows = (Integer) hibernateTemplate.execute(new HibernateCallback() + { - getHibernateTemplate().flush(); + // + // HibernateCallback + // + + public final Object doInHibernate(final Session session) throws HibernateException, + SQLException + { + // NOTE: 'VERSIONED' makes modification time modified too + return session + .createQuery( + "UPDATE VERSIONED " + + ExperimentPE.class.getSimpleName() + + " SET deletion = :deletion WHERE deletion IS NULL AND id IN (:ids) ") + .setParameter("deletion", deletion) + .setParameterList("ids", TechId.asLongs(experimentIds)).executeUpdate(); + } + }); + if (operationLog.isInfoEnabled()) + { + operationLog.info(String.format("trashing %d experiments", updatedRows)); + } + hibernateTemplate.flush(); + return updatedRows; } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/SampleDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/SampleDAO.java index 2c6e7f80676..5f1d9619aad 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/SampleDAO.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/SampleDAO.java @@ -16,6 +16,7 @@ package ch.systemsx.cisd.openbis.generic.server.dataaccess.db; +import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -25,11 +26,13 @@ import java.util.Set; import org.apache.log4j.Logger; import org.hibernate.Criteria; import org.hibernate.FetchMode; +import org.hibernate.HibernateException; import org.hibernate.SQLQuery; import org.hibernate.Session; import org.hibernate.StatelessSession; import org.hibernate.criterion.Criterion; import org.hibernate.criterion.DetachedCriteria; +import org.hibernate.criterion.Projections; import org.hibernate.criterion.Restrictions; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.support.JdbcAccessor; @@ -464,27 +467,48 @@ public class SampleDAO extends AbstractGenericEntityWithPropertiesDAO<SamplePE> scheduleRemoveFromFullTextIndex(ids); } - public void trash(final List<TechId> sampleIds, final DeletionPE deletion) + public int trash(final List<TechId> sampleIds, final DeletionPE deletion) throws DataAccessException { - // TODO 2011-06-16, Piotr Buczek: could be done faster with bulk update - for (TechId sampleId : sampleIds) + if (sampleIds.isEmpty()) { - SamplePE sample = loadByTechId(sampleId); - if (sample.getDeletion() == null) - { - sample.setDeletion(deletion); - } + return 0; } + final HibernateTemplate hibernateTemplate = getHibernateTemplate(); + int updatedRows = (Integer) hibernateTemplate.execute(new HibernateCallback() + { - getHibernateTemplate().flush(); + // + // HibernateCallback + // + + public final Object doInHibernate(final Session session) throws HibernateException, + SQLException + { + // NOTE: 'VERSIONED' makes modification time modified too + return session + .createQuery( + "UPDATE VERSIONED " + + SamplePE.class.getSimpleName() + + " SET deletion = :deletion WHERE deletion IS NULL AND id IN (:ids) ") + .setParameter("deletion", deletion) + .setParameterList("ids", TechId.asLongs(sampleIds)).executeUpdate(); + } + }); + if (operationLog.isInfoEnabled()) + { + operationLog.info(String.format("trashing %d samples", updatedRows)); + } + hibernateTemplate.flush(); + return updatedRows; } - @SuppressWarnings("unchecked") - public Set<TechId> listParents(final Collection<TechId> children, final TechId relationship) + public Set<TechId> listSampleIdsByChildrenIds(final Collection<TechId> children, + final TechId relationship) { final String query = "select sample_id_parent from sample_relationships where sample_id_child in (:ids) and relationship_id = :r "; + @SuppressWarnings("unchecked") final List<? extends Number> results = (List<? extends Number>) getHibernateTemplate().execute(new HibernateCallback() { @@ -499,10 +523,65 @@ public class SampleDAO extends AbstractGenericEntityWithPropertiesDAO<SamplePE> Set<TechId> result = transformNumbers2TechIdSet(results); if (operationLog.isDebugEnabled()) { - operationLog.debug(String.format("%d sample parents(s) have been found.", + operationLog.debug(String.format("found %d sample parents for given children", results.size())); } return result; } + public Set<TechId> listSampleIdsByParentIds(final Collection<TechId> parents) + { + final String query = + "SELECT sample_id_child FROM " + TableNames.SAMPLE_RELATIONSHIPS_TABLE + + " WHERE sample_id_parent IN (:ids)"; + @SuppressWarnings("unchecked") + final List<? extends Number> results = + (List<? extends Number>) getHibernateTemplate().execute(new HibernateCallback() + { + + public final Object doInHibernate(final Session session) + { + final List<Long> longIds = TechId.asLongs(parents); + return session.createSQLQuery(query).setParameterList("ids", longIds) + .list(); + } + }); + Set<TechId> result = transformNumbers2TechIdSet(results); + if (operationLog.isDebugEnabled()) + { + operationLog.info(String.format("found %d sample children for given parents", + results.size())); + } + return result; + } + + public List<TechId> listSampleIdsByContainerIds(final Collection<TechId> containers) + { + final DetachedCriteria criteria = DetachedCriteria.forClass(SamplePE.class); + final List<Long> longIds = TechId.asLongs(containers); + criteria.setProjection(Projections.id()); + criteria.add(Restrictions.in("container.id", longIds)); + final List<Long> results = cast(getHibernateTemplate().findByCriteria(criteria)); + if (operationLog.isDebugEnabled()) + { + operationLog.info(String.format("found %s sample components for given containers", + results.size())); + } + return transformNumbers2TechIdList(results); + } + + public List<TechId> listSampleIdsByExperimentIds(final Collection<TechId> experiments) + { + final DetachedCriteria criteria = DetachedCriteria.forClass(SamplePE.class); + final List<Long> longIds = TechId.asLongs(experiments); + criteria.setProjection(Projections.id()); + criteria.add(Restrictions.in("experimentInternal.id", longIds)); + final List<Long> results = cast(getHibernateTemplate().findByCriteria(criteria)); + // if (operationLog.isDebugEnabled()) + // { + operationLog.info(String.format("found %s samples for given experiments", results.size())); + // } + return transformNumbers2TechIdList(results); + } + } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericDataSetTypeSlaveServerPlugin.java b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericDataSetTypeSlaveServerPlugin.java index ece3c1d0f9c..6e4b59f0249 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericDataSetTypeSlaveServerPlugin.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/plugin/generic/server/GenericDataSetTypeSlaveServerPlugin.java @@ -27,6 +27,7 @@ import ch.systemsx.cisd.openbis.generic.server.batch.DataSetBatchUpdate; import ch.systemsx.cisd.openbis.generic.server.business.bo.IDataSetTable; import ch.systemsx.cisd.openbis.generic.server.business.bo.ITrashBO; import ch.systemsx.cisd.openbis.generic.server.plugin.IDataSetTypeSlaveServerPlugin; +import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DeletionType; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewDataSet; import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE; @@ -61,7 +62,7 @@ public class GenericDataSetTypeSlaveServerPlugin implements IDataSetTypeSlaveSer case TRASH: ITrashBO trashBO = businessObjectFactory.createTrashBO(session); trashBO.createDeletion(reason); - trashBO.trashDataSets(dataSets); + trashBO.trashDataSets(TechId.createList(dataSets)); break; } } -- GitLab