grails - Grails 3 中一对多域的深层复制

标签 grails grails-orm

我很困惑如何实现这个或者它是否真的可能/合适。我和我的同事正在使用 Grails 3 为客户构建一个 Web 应用程序。他创建了初始域,我猜测它是来自移动应用程序的 Realm 模型的几乎一对一的副本。此后,我修改了它们,试图使某种形式的深度克隆发挥作用,因为三个域具有一对多关系。

问题

我将如何创建域的深拷贝?我尝试了建议的答案,但收效甚微:

从不同地方汲取想法,我制定了如下所示的clone(Domain)方法。它几乎可以工作(我认为),但是集合抛出HibernateException - 发现对集合的共享引用:Location.equipments有问题。

在 Controller 中调用为:

def copy() {
    Survey.clone(Survey.get(params.id))
    redirect action: 'index'
}

有什么想法或指导吗?

目前的域名如下:

class Survey {

    int id
    String name
    String contactName
    String contactEmail
    String facilityAddress
    String facilityCity
    String facilityStateProvince
    String facilityZip
    String distributorName
    String distributorEmail
    String distributorPhoneNumber

    static Survey clone(Survey self) {
        Survey clone = new Survey()
        String exclude = "locations"

        clone.properties = self.properties.findAll {
            it.key != exclude
        }

        self.locations.each {
            Location copy = Location.clone it
            clone.addToLocations copy
        }

        clone.save()
    }

    static transients = ['clone']
    static belongsTo = User
    static hasMany = [locations: Location]
}
<小时/>
class Location {
    int id
    String name
    String[] hazardsPresent
    HazardType[] hazardTypes
    ExposureArea[] exposureArea
    RiskLevel exposureLevel
    String comments
    byte[] picture

    static Location clone(Location self) {
        Location clone = new Location()
        String[] excludes = ['equipment', 'products']

        clone.properties = self.properties.findAll {
            !(it.key in excludes)
        }

        self.equipments.each {
            Equipment copy = Equipment.clone it
            self.addToEquipments copy
        }

        self.products.each {
            RecommendedProduct copy = new RecommendedProduct()
            copy.properties = it.properties
            copy.save()
            clone.addToProducts copy
        }

        clone.save()
    }

    static transients = ['clone']
    static belongsTo = Survey
    static hasMany = [equipments: Equipment, products: RecommendedProduct]
    static constraints = {
        picture(maxSize: 1024 * 1024)
    }
}
<小时/>
class Equipment {
    int id
    EquipmentType type
    String name
    Brand brand

   // Redacted 26 boolean properties
   // ...

    static Equipment clone(Equipment self) {
        Equipment clone = new Equipment()
        String exclude = "extras"

        clone.properties = self.properties.findAll {
            it.key != exclude
        }

        self.extras.each {
            EquipmentQuestionExtra copy = new EquipmentQuestionExtra()
            copy.properties = it.properties
            copy.save()
            clone.addToExtras copy
        }

        clone.save()
    }

    static transients = ['clone']
    static belongsTo = Location
    static hasMany = [extras: EquipmentQuestionExtra]
}
<小时/>
class RecommendedProduct {
    int productId
    int quantityChosen
    String comment

    static belongsTo = Location
}
<小时/>
class EquipmentQuestionExtra {
    int id
    String questionText
    String comment
    byte[] picture

    static belongsTo = Equipment
    static constraints = {
        picture(maxSize: 1024 * 1024)
    }
}

最佳答案

您的克隆方法可能有问题:您克隆了“所有”属性,包括 ID,这对于深度克隆来说是一个坏主意。 This thread说明当一个对象与休眠缓存中的另一个对象具有相同的属性但具有另一个引用时,会引发错误。

因此,您只需将对象的 id 属性设置为 null (或将其从属性副本中排除)即可强制 Hibernate 检测到它是新的目的。如果仍然无法正常工作,请调用 discard保存之前对对象执行方法。

关于grails - Grails 3 中一对多域的深层复制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39157408/

相关文章:

django - Grails 模板继承

grails - 具有可重复输入的处理形式

Grails 对象关系,其中拥有方没有对其所有者的引用

hibernate - Grails/GORM : org. hibernate.AssertionFailure: xyz 中的 null id(发生异常后不刷新 session )

hibernate - 如何使用投影和标准获得不同的结果

grails - 依赖注入(inject)在使用邮件插件的 grails 作业中不起作用

android - Grails模板

Grails GSP 编译?

Grails Gorm : Object references an unsaved transient instance

grails - 使用 Grails 域检索数据默认返回一个类键