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 49240394e26010b00e37c4e02b04cb46783a07bc..db00e67a35782d17679a1367f035d9d008fe8cc6 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 @@ -2410,9 +2410,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt checkSession(sessionToken); IDeletionDAO deletionDAO = getDAOFactory().getDeletionDAO(); - // NOTE: - // - we can't do bulk deletions to preserve original reason - // - we keep findTrashed... methods with collections as arguments for future use + // NOTE: we can't do bulk deletions to preserve original reasons for (TechId deletionId : deletionIds) { DeletionPE deletion = deletionDAO.getByTechId(deletionId); @@ -2423,8 +2421,15 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt List<String> trashedDataSets = deletionDAO.findTrashedDataSetCodes(singletonList); deleteDataSets(sessionToken, trashedDataSets, deletionReason, deletionType); - List<TechId> trashedSamples = deletionDAO.findTrashedSampleIds(singletonList); - deleteSamples(sessionToken, trashedSamples, deletionReason, deletionType); + // we need to first delete components and then containers not to break constraints + List<TechId> trashedComponentSamples = + deletionDAO.findTrashedComponentSampleIds(singletonList); + deleteSamples(sessionToken, trashedComponentSamples, deletionReason, deletionType); + List<TechId> trashedNonComponentSamples = + deletionDAO.findTrashedNonComponentSampleIds(singletonList); + deleteSamples(sessionToken, trashedNonComponentSamples, deletionReason, deletionType); + // List<TechId> trashedSamples = deletionDAO.findTrashedSampleIds(singletonList); + // deleteSamples(sessionToken, trashedSamples, deletionReason, deletionType); List<TechId> trashedExperiments = deletionDAO.findTrashedExperimentIds(singletonList); deleteExperiments(sessionToken, trashedExperiments, deletionReason, deletionType); 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 bced950f11bb93af2fa0f637df1e4d1bb3211b75..e0c2e5085f1ec3615d874683ddbd00035c85c990 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 @@ -24,6 +24,7 @@ import org.apache.log4j.Logger; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; +import org.hibernate.criterion.Criterion; import org.hibernate.criterion.DetachedCriteria; import org.hibernate.criterion.Projections; import org.hibernate.criterion.Restrictions; @@ -52,6 +53,10 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind; final class DeletionDAO extends AbstractGenericEntityDAO<DeletionPE> implements IDeletionDAO { + private static final String DELETION_ID = "deletion.id"; + + private static final String CONTAINER_ID = "containerId"; + /** * This logger does not output any SQL statement. If you want to do so, you had better set an * appropriate debugging level for class {@link JdbcAccessor}. </p> @@ -127,6 +132,18 @@ final class DeletionDAO extends AbstractGenericEntityDAO<DeletionPE> implements return findTrashedEntityIds(deletionIds, EntityKind.SAMPLE); } + public List<TechId> findTrashedNonComponentSampleIds(final List<TechId> deletionIds) + { + return findTrashedEntityIds(deletionIds, EntityKind.SAMPLE, + Restrictions.isNull(CONTAINER_ID)); + } + + public List<TechId> findTrashedComponentSampleIds(final List<TechId> deletionIds) + { + return findTrashedEntityIds(deletionIds, EntityKind.SAMPLE, + Restrictions.isNotNull(CONTAINER_ID)); + } + public List<TechId> findTrashedExperimentIds(final List<TechId> deletionIds) { return findTrashedEntityIds(deletionIds, EntityKind.EXPERIMENT); @@ -138,7 +155,7 @@ final class DeletionDAO extends AbstractGenericEntityDAO<DeletionPE> implements DetachedCriteria.forClass(EntityKind.DATA_SET.getDeletedEntityClass()); final List<Long> longIds = TechId.asLongs(deletionIds); criteria.setProjection(Projections.property("code")); - criteria.add(Restrictions.in("deletion.id", longIds)); + criteria.add(Restrictions.in(DELETION_ID, longIds)); final List<String> results = cast(getHibernateTemplate().findByCriteria(criteria)); operationLog.info(String.format("found %s trashed %s(s)", results.size(), EntityKind.DATA_SET.name())); @@ -146,13 +163,17 @@ final class DeletionDAO extends AbstractGenericEntityDAO<DeletionPE> implements } private List<TechId> findTrashedEntityIds(final List<TechId> deletionIds, - final EntityKind entityKind) + final EntityKind entityKind, Criterion... additionalCriteria) { final DetachedCriteria criteria = DetachedCriteria.forClass(entityKind.getDeletedEntityClass()); final List<Long> longIds = TechId.asLongs(deletionIds); criteria.setProjection(Projections.id()); - criteria.add(Restrictions.in("deletion.id", longIds)); + criteria.add(Restrictions.in(DELETION_ID, longIds)); + for (Criterion criterion : additionalCriteria) + { + criteria.add(criterion); + } final List<Long> results = cast(getHibernateTemplate().findByCriteria(criteria)); operationLog .info(String.format("found %s trashed %s(s)", results.size(), entityKind.name())); diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DeletedSamplePE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DeletedSamplePE.java index 694cdedc7bf03ab779cf40d13bedba87062263b0..18f2ebf0332599fe31db941e7029c191dd111023 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DeletedSamplePE.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/DeletedSamplePE.java @@ -16,6 +16,7 @@ package ch.systemsx.cisd.openbis.generic.shared.dto; +import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; @@ -46,6 +47,8 @@ public class DeletedSamplePE extends AbstractDeletedEntityPE private transient Long id; + private Long containerId; + @Id @SequenceGenerator(name = SequenceNames.SAMPLE_SEQUENCE, sequenceName = SequenceNames.SAMPLE_SEQUENCE, allocationSize = 1) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = SequenceNames.SAMPLE_SEQUENCE) @@ -60,6 +63,17 @@ public class DeletedSamplePE extends AbstractDeletedEntityPE this.id = id; } + @Column(name = ColumnNames.PART_OF_SAMPLE_COLUMN, nullable = false, insertable = false, updatable = false) + public Long getContainerId() + { + return containerId; + } + + public void setContainerId(final Long containerId) + { + this.containerId = containerId; + } + // // Object //