我很困惑如何实现这个或者它是否真的可能/合适。我和我的同事正在使用 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/