Grails删除孩子

时间:2014-01-22 18:38:02

标签: grails gorm grails-2.0 grails-domain-class

我有一个类,DigitalObject,它基本上是一个url的容器和上次修改的日期。

class DigitalObject {
  String url
  Date lastUpdated
}

我有两个类使用DigitalObjects来引用与它们相关的不同URL

class Video {
   DigitalObject englishVersion
   DigitalObject frenchVersion
}

class Image {
   DigitalObject thumbnailImage
   DigitalObject fullSizeImage
}

我在绘制映射时遇到了很多麻烦。

我希望能够删除一个DigitalObject并让GORM负责将其从父母身上删除。

如果我在尝试删除digitalObject时将其保留在上面,我会收到外键约束违规。

如果我在父端添加hasOne映射,我会收到一条错误,指出要指定关系的另一面,但我不清楚在哪里这样做,因为DigitalObject可以属于图像或视频。像这样。

class Video {
   static hasOne = [englishVersion: DigitalObject, frenchVersion: DigitalObject]
}

在子类中添加belongsTo会导致相同的外键约束错误。像这样。

class DigitalObject {
  String url
  Date lastUpdated

  static belongsTo = [Image, Video]
}

我是否必须放弃并手动将其从父程序中删除?

提前感谢您的任何帮助,对不起,如果对其他商品有所回答,我无法提出搜索查询,提供处理案件的结果,例如我的,但我确信这不是一个不常见的用例。

2014年1月24日编辑

尝试安德鲁的建议,我的实际域类比我使用的例子复杂得多,因此我的beforeDelete()最终如下所示,这非常难看并且可能很难维护。

def beforeDelete() {
    DigitalObject.withNewSession {
        def imageThumbnailImages = Image.findAllByThumbnailImage(this)
        if (imageThumbnailImages) {
            imageThumbnailImages.each { image ->
                image.thumbnailImage = null
                image.save(flush: true)
            }
        }
        def imagePreviewImages = Image.findAllByPreviewImage(this)
        if (imagePreviewImages) {
            imagePreviewImages.each { image ->
                image.previewImage = null
                image.save(flush: true)
            }
        }
        def imageFullImages = Image.findAllByFullImage(this)
        if (imageFullImages) {
            imageFullImages.each { image ->
                image.fullImage = null
                image.save(flush: true)
            }
        }
        def videoThumbnailImages = Video.findAllByThumbnailImage(this)
        if (videoThumbnailImages) {
            videoThumbnailImages.each { image ->
                image.thumbnailImage = null
                image.save(flush: true)
            }
        }
        def videoPreviewImages = Video.findAllByPreviewImage(this)
        if (videoPreviewImages) {
            videoPreviewImages.each { image ->
                image.previewImage = null
                image.save(flush: true)
            }
        }
        def videoFullVideosEng = Video.findAllByFullVideoEng(this)
        if (videoFullVideosEng) {
            videoFullVideosEng.each { video ->
                video.fullVideoEng = null
                video.save(flush: true)
            }
        }
        def videoFullVideosFra = Video.findAllByFullVideoFra(this)
        if (videoFullVideosFra) {
            videoFullVideosFra.each { video ->
                video.fullVideoFra = null
                video.save(flush: true)
            }
        }
        def captionsEngVideos = Video.findAllByCaptionsEng(this)
        if (captionsEngVideos) {
            captionsEngVideos.each { videos ->
                videos.captionsEng = null
                videos.save(flush: true)
            }
        }
        def captionsFraVideos = Video.findAllByCaptionsFra(this)
        if (captionsFraVideos) {
            captionsFraVideos.each { video ->
                video.captionsFra = null
                video.save(flush: true)
            }
        }
        def signLanguageEngVideos = Video.findAllBySignLanguageEng(this)
        if (signLanguageEngVideos) {
            signLanguageEngVideos.each { video ->
                video.signLanguageEng = null
                video.save(flush: true)
            }
        }
        def signLanguageFraVideos = Video.findAllBySignLanguageEng(this)
        if (signLanguageFraVideos) {
            signLanguageFraVideos.each { video ->
                video.signLanguageFra = null
                video.save(flush: true)
            }
        }
    }

2 个答案:

答案 0 :(得分:1)

我有一个类似的域类,可以由不同的父级拥有,我的级联删除按预期工作。所以使用你的课程,你试过这个:

class DigitalObject {
    String url
    Date lastUpdated

    Image image
    Video video

    static belongsTo = [
         image: Image, 
         video: Video
    ]

编辑:从下面的约束中删除了方括号!

    static constraints = {
        image( nullable : true )
        video( nullable : true )
    }

}

不确定您的图像/视频上是否还有onOne。但尝试使用和不使用。

答案 1 :(得分:0)

这很丑陋,可能不是最好的方法,但因为我无法让其他方法建议可靠地工作,并且由于我想尽可能对域类进行最小的更改,因为我的project并不是唯一使用它们的人。

我将以下方法添加到我的DigitalObjectController。

def deleteFromMediaAsset(Long id, String parentClass, String parentProperty, String parentId) {
    def digitalObjectInstance = DigitalObject.get(id)
    if (!digitalObjectInstance) {
        flash.message = message(code: 'default.not.found.message', args: [
            message(code: 'digitalObject.label', default: 'DigitalObject'),
            id
        ])
        redirect(controller: parentClass, action: 'edit', id: parentId)
        return
    }

    try {
        def classOfParent = grailsApplication.domainClasses.find {
            it.clazz.simpleName == parentClass.capitalize()
        }.clazz

        def parentInstance = classOfParent.get(parentId)
        parentInstance.setProperty(parentProperty, null)
        digitalObjectInstance.delete(flush: true)
        flash.message = message(code: 'default.deleted.message', args: [
            message(code: 'digitalObject.label', default: 'DigitalObject'),
            id
        ])
        redirect(controller: parentClass, action: 'edit', id: parentId)
    }
    catch (DataIntegrityViolationException e) {
        flash.message = message(code: 'default.not.deleted.message', args: [
            message(code: 'digitalObject.label', default: 'DigitalObject'),
            id
        ])
        redirect(controller: parentClass, action: 'edit', id: parentId)
    }
}

基本上我传递父Image或Video类和ID以及DigitalObject引用的属性和我想删除的DigialObject的ID。我在父对象上将属性设置为null,然后删除DigitalObject。

丑陋但它现在有效,祝我好运。