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 721b9cf491ec60f7d25072a6b9c1ac486e32c790..2c6e7f8067616c9568e0d6a5ad9ceb290377d58f 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 @@ -387,6 +387,12 @@ public class SampleDAO extends AbstractGenericEntityWithPropertiesDAO<SamplePE> "SELECT perm_id FROM " + TableNames.SAMPLES_TABLE + " WHERE id = :sId"; final String sqlDeleteProperties = "DELETE FROM " + TableNames.SAMPLE_PROPERTIES_TABLE + " WHERE samp_id = :sId"; + final String sqlAttachmentContentIds = + "SELECT exac_id FROM " + TableNames.ATTACHMENTS_TABLE + " WHERE samp_id = :sId"; + final String sqlDeleteAttachmentContents = + "DELETE FROM " + TableNames.ATTACHMENT_CONTENT_TABLE + " WHERE id in (:aIds)"; + final String sqlDeleteAttachments = + "DELETE FROM " + TableNames.ATTACHMENTS_TABLE + " WHERE samp_id = :sId"; final String sqlDeleteSample = "DELETE FROM " + TableNames.SAMPLES_TABLE + " WHERE id = :sId"; final String sqlInsertEvent = @@ -404,6 +410,12 @@ public class SampleDAO extends AbstractGenericEntityWithPropertiesDAO<SamplePE> session.createSQLQuery(sqlDeleteProperties); final SQLQuery sqlQueryDeleteSample = session.createSQLQuery(sqlDeleteSample); final SQLQuery sqlQueryInsertEvent = session.createSQLQuery(sqlInsertEvent); + final SQLQuery sqlQueryAttachmentContentIds = + session.createSQLQuery(sqlAttachmentContentIds); + final SQLQuery sqlQueryDeleteAttachments = + session.createSQLQuery(sqlDeleteAttachments); + final SQLQuery sqlQueryDeleteAttachmentContents = + session.createSQLQuery(sqlDeleteAttachmentContents); sqlQueryInsertEvent.setParameter("eventType", EventType.DELETION.name()); sqlQueryInsertEvent.setParameter("reason", reason); sqlQueryInsertEvent.setParameter("registratorId", registrator.getId()); @@ -418,6 +430,18 @@ public class SampleDAO extends AbstractGenericEntityWithPropertiesDAO<SamplePE> // delete properties sqlQueryDeleteProperties.setParameter("sId", techId.getId()); sqlQueryDeleteProperties.executeUpdate(); + // delete attachments + sqlQueryAttachmentContentIds.setParameter("sId", techId.getId()); + List<Long> attachmentContentIds = + cast(sqlQueryAttachmentContentIds.list()); + if (attachmentContentIds.size() > 0) + { + sqlQueryDeleteAttachments.setParameter("sId", techId.getId()); + sqlQueryDeleteAttachments.executeUpdate(); + sqlQueryDeleteAttachmentContents.setParameterList("aIds", + attachmentContentIds); + sqlQueryDeleteAttachmentContents.executeUpdate(); + } // delete sample sqlQueryDeleteSample.setParameter("sId", techId.getId()); sqlQueryDeleteSample.executeUpdate(); diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/AttachmentContentPE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/AttachmentContentPE.java index e3f00e7c308f2e21fdff3c2e0d74268bb5a7cec7..8edfc7430ad0e529a122106d1bab26a9ab809f09 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/AttachmentContentPE.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/AttachmentContentPE.java @@ -30,6 +30,7 @@ import org.hibernate.annotations.Type; import org.hibernate.validator.NotNull; import ch.systemsx.cisd.openbis.generic.shared.IServer; +import ch.systemsx.cisd.openbis.generic.shared.basic.IIdHolder; /** * An attachment content <i>Persistent Entity</i>. @@ -38,7 +39,7 @@ import ch.systemsx.cisd.openbis.generic.shared.IServer; */ @Entity @Table(name = TableNames.ATTACHMENT_CONTENT_TABLE) -public class AttachmentContentPE implements Serializable +public class AttachmentContentPE implements IIdHolder, Serializable { private static final long serialVersionUID = IServer.VERSION; diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentPE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentPE.java index 52f64fcc000ac4a799d51be9f0b408b326a0546e..f3f595074c48426bb8536463c2d9ab3e03dab558 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentPE.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ExperimentPE.java @@ -314,7 +314,8 @@ public class ExperimentPE extends AttachmentHolderPE implements } @Override - @OneToMany(fetch = FetchType.LAZY, mappedBy = "experimentParentInternal") + @OneToMany(fetch = FetchType.LAZY, mappedBy = "experimentParentInternal", cascade = CascadeType.ALL) + @Cascade(value = org.hibernate.annotations.CascadeType.DELETE_ORPHAN) @IndexedEmbedded(prefix = SearchFieldConstants.PREFIX_ATTACHMENT) @Fetch(FetchMode.SUBSELECT) protected Set<AttachmentPE> getInternalAttachments() diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ProjectPE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ProjectPE.java index a872e9812a50a9c4c79746f6df494c30185dbb09..45044d566a042a6bb0cf24a7ae1c846bfc534139 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ProjectPE.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/ProjectPE.java @@ -22,6 +22,7 @@ import java.util.Date; import java.util.List; import java.util.Set; +import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; @@ -40,6 +41,7 @@ import javax.persistence.Version; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ToStringBuilder; +import org.hibernate.annotations.Cascade; import org.hibernate.annotations.Fetch; import org.hibernate.annotations.FetchMode; import org.hibernate.annotations.Generated; @@ -326,7 +328,8 @@ public final class ProjectPE extends AttachmentHolderPE implements Comparable<Pr } @Override - @OneToMany(fetch = FetchType.LAZY, mappedBy = "projectParentInternal") + @OneToMany(fetch = FetchType.LAZY, mappedBy = "projectParentInternal", cascade = CascadeType.ALL) + @Cascade(value = org.hibernate.annotations.CascadeType.DELETE_ORPHAN) @IndexedEmbedded(prefix = SearchFieldConstants.PREFIX_ATTACHMENT) @Fetch(FetchMode.SUBSELECT) protected Set<AttachmentPE> getInternalAttachments() diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SamplePE.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SamplePE.java index 2f7d6c39d183fab617d7ae47013e161f02d372ba..9d68145fc9b6a117e8aa9b7a045c2bad0b368a47 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SamplePE.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SamplePE.java @@ -694,7 +694,8 @@ public class SamplePE extends AttachmentHolderPE implements IIdAndCodeHolder, Co } @Override - @OneToMany(fetch = FetchType.LAZY, mappedBy = "sampleParentInternal") + @OneToMany(fetch = FetchType.LAZY, mappedBy = "sampleParentInternal", cascade = CascadeType.ALL) + @Cascade(value = org.hibernate.annotations.CascadeType.DELETE_ORPHAN) @IndexedEmbedded(prefix = SearchFieldConstants.PREFIX_ATTACHMENT) @Fetch(FetchMode.SUBSELECT) protected Set<AttachmentPE> getInternalAttachments() diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExperimentDAOTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExperimentDAOTest.java index 80574a7c42ef61e93a6c995f19ed8cd20b85e702..baa558a58e3448eb02d66721541024f78badaab3 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExperimentDAOTest.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/ExperimentDAOTest.java @@ -274,26 +274,38 @@ public class ExperimentDAOTest extends AbstractDAOTest } } - @Test(expectedExceptions = DataIntegrityViolationException.class) - public final void testDeleteFailWithAttachments() + private static final String ATT_CONTENTS_TABLE = "attachment_contents"; + + @Test + public final void testDeleteWithAttachments() { final IExperimentDAO experimentDAO = daoFactory.getExperimentDAO(); final ExperimentPE deletedExperiment = findExperiment("/CISD/DEFAULT/EXP-X"); // Deleted experiment should have attachments which prevent it from deletion. - // Other connections which also prevent sample deletion should be empty in this test. + // Other connections which also prevent experiment deletion should be empty in this test. // Currently there is no such experiment in test DB so we first add an attachment - // to an experiment empty experiment (with no connections). + // to an empty experiment (with no connections). + int rowsInAttachmentContents = countRowsInTable(ATT_CONTENTS_TABLE); + AttachmentPE attachment = CommonTestUtils.createAttachment(); + attachment.setRegistrator(deletedExperiment.getRegistrator()); daoFactory.getAttachmentDAO().createAttachment(attachment, deletedExperiment); + assertEquals(rowsInAttachmentContents + 1, countRowsInTable(ATT_CONTENTS_TABLE)); + assertFalse(deletedExperiment.getAttachments().isEmpty()); assertTrue(deletedExperiment.getDataSets().isEmpty()); assertTrue(deletedExperiment.getSamples().isEmpty()); // delete experimentDAO.delete(deletedExperiment); + + // test successful deletion of experiment, attachment & content + assertNull(experimentDAO.tryGetByTechId(TechId.create(deletedExperiment))); + assertNull(daoFactory.getAttachmentDAO().tryGetByTechId(TechId.create(attachment))); + assertEquals(rowsInAttachmentContents, countRowsInTable(ATT_CONTENTS_TABLE)); } @Test(expectedExceptions = DataIntegrityViolationException.class) diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/SampleDAOTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/SampleDAOTest.java index e54c7c20f5928e0c865894dc21547ae61f5efbb5..ceed326a2d5be1500dad39d6cbace2b8c005015d 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/SampleDAOTest.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/SampleDAOTest.java @@ -47,12 +47,12 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.EventPE; import ch.systemsx.cisd.openbis.generic.shared.dto.EventPE.EntityType; import ch.systemsx.cisd.openbis.generic.shared.dto.EventType; import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE; -import ch.systemsx.cisd.openbis.generic.shared.dto.SpacePE; import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE; import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE; import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePropertyPE; import ch.systemsx.cisd.openbis.generic.shared.dto.SampleRelationshipPE; import ch.systemsx.cisd.openbis.generic.shared.dto.SampleTypePE; +import ch.systemsx.cisd.openbis.generic.shared.dto.SpacePE; import ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind; import ch.systemsx.cisd.openbis.generic.shared.util.HibernateUtils; @@ -370,20 +370,37 @@ public final class SampleDAOTest extends AbstractDAOTest } } - @Test(expectedExceptions = DataIntegrityViolationException.class) - public final void testDeleteFailWithAttachments() + private static final String ATT_CONTENTS_TABLE = "attachment_contents"; + + @Test + public final void testDeleteWithAttachments() { + final ISampleDAO sampleDAO = daoFactory.getSampleDAO(); final SamplePE deletedSample = findSample("3VCP6", "CISD"); - // Deleted sample should have attachments which prevent it from deletion. - // Other connections which also prevent sample deletion should be empty in this test. + // Deleted sample should have attachments which should be deleted as well as the sample. assertFalse(deletedSample.getAttachments().isEmpty()); + List<TechId> attachmentIds = TechId.createList(deletedSample.getAttachments()); + // Other connections which would prevent sample deletion should be empty in this test. assertTrue(deletedSample.getDatasets().isEmpty()); assertTrue(deletedSample.getGenerated().isEmpty()); assertTrue(deletedSample.getContained().isEmpty()); + int rowsInAttachmentContents = countRowsInTable(ATT_CONTENTS_TABLE); + // delete deleteSample(deletedSample); + + // test successful deletion of sample + assertNull(sampleDAO.tryGetByTechId(TechId.create(deletedSample))); + + // test successful deletion of attachments & their contents + for (TechId attachmentId : attachmentIds) + { + assertNull(daoFactory.getAttachmentDAO().tryGetByTechId(attachmentId)); + } + assertEquals(rowsInAttachmentContents - attachmentIds.size(), + countRowsInTable(ATT_CONTENTS_TABLE)); } @Test(expectedExceptions = DataIntegrityViolationException.class)