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 10a25de603ee055c7fe9006b832ed3c919d04680..9949b4a770392bcbc846f494e6906c994d8268b4 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 170707cc51d3ea5f7c6a69e91f8c260dbcfa784c..4c73d12f65ee6c42c4b804447f2393eec07ea8db 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 3a4d955105c3596eace446586f098daec1bedd6e..20348f239ed3d73dd30ab3cd3bff3bbc1fbfcb18 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 270b74eb5b4454d862f8cd84f2a6dce453f5ebcc..d3bb6d8ffc3b250dc0510a97d772153eb2f84c7c 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 668340e2f37c6a41d1d6433e42b6efd2e035bdf1..6d4512b92111263d5aad09625e277872afa28b63 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 68a1b38f937e42961ef7112126130bd8a0493e3e..1fa3e8fcc176a2e41fd8a798af9e8c37dc0eacea 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 e155d2689ded13ac1660d7158bef12212b6f3679..300a60a559c61ebed9107362d109208016bb6b07 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 5c2f74eb54047a9a8a3ee3839d950c91b4ac53cb..5942b4b7f07601b0d445a63e0f49033243de4a01 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 8132222cf562894f429ceb86e3e8dccb9080f7b2..de43071759f206b50b0b0052c9f2359ef3d67efe 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 67fb17eb21e8355559a9645c9701feb5810a2f64..d79f4e2a933a9ca0249a3b1a7c01281071add610 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 8a52959b90e4255d20bf7fb37df99c1007f345b1..924057cf6fef822f38fdf30449993a4e34091136 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 b136bfeafa3c809a7084504f7fd22acc23c7ad7d..bb35bce72172e509518765e730103512adb72c43 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 8eb96cea9308f049b95304d55d145a6d785cf630..650a1753641d783cfefadfb6e4123483daf25dcb 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 98d6a1632c93460dc3b1db32d461d0a4f89e3592..756de7db2665d3725ad1962b9ddb996c30eb814a 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 2c6e7f8067616c9568e0d6a5ad9ceb290377d58f..5f1d9619aad0886bbb01b4c2de48bb0fbbd20a97 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 ece3c1d0f9c516be8a828bbf09bbaad47825805b..6e4b59f02495a52bd1a7a9e62795973c88f09c19 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; } }