问题描述
我有几个域类,其中用户界面包含
重复命令。作为这些命令实现的一部分,
我在相应的域类中实现了 clone()
方法。
我一直在尝试纠正我不恰当地使用 new
而不是super.clone(),
,所以当我想为Grails域
类做同样的事时,我想知道如何使用 super.clone()
来获得一个克隆可能
与 GORM
/ Hibernate持久性进行交互。特别是,我是
想知道处理隐式id属性的正确方法。如果
只是 super.clone()
,则不做任何事情,稍后尝试 save()
the
克隆的实例,它能正常工作(创建一个新的持久性
条目吗?),还是会出现某种错误或无声失败结果?
什么是复制Grails域
实例的正确或首选方法?
将以下方法添加到metaClass的接口 GormInstanceApi
,所有域都实现它。
:
def cloneForDomains = {def cloned = delegate.class.newInstance();
cloned.properties = delegate.properties;
return cloned;}
然后:
org.grails.datastore.gorm.GormInstanceApi.clone = cloneForDomains;
恭喜!现在您可以使用 clone
方法,例如 save
, delete
.....
USE CASE:
Person p = Person.get(1);
克隆人= p.clone();
cloned.id = null;
cloned.save();
更新:您也可以循环所有网域类别:
grailsApplication.getDomainClasses()。each {cls->
cls.metaClass.clone = cloneForDomains
}
更新: 为深度克隆:
grailsApplication.getDomainClasses()。each {cls->
cls.metaClass.clone = {
return deepClone(delegate);
已知 I have several domain classes for which the user interface includesa "duplicate" command. As part of the implementation of those commands,I have implemented I have been trying to correct my bad habit of improperly implementingclone() (in general) based on use of " What is the proper or preferred way to duplicate a Grails domaininstance? Add the following method to metaClass of the interface then : Congrats! now you can use USE CASE : UPDATE : you can loop all domain classes also : UPDATE : for deep clone : known that 这篇关于正确实施clone()对于Domain Classes复制Grails域实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! deepClone code $是一个方法如下:
pre $ 对象deepClone(domainInstanceToClone){
/ / TODO:PRECISA ENTENDER ISSO! MB-249 no youtrack
// Algumas类chegam aqui com nome da classe + _ $$ _ javassist_XX $ b $ if(domainInstanceToClone.getClass()。name.contains(_ javassist))
return null
//我们想要克隆的实例的目标实例
//递归
def newDomainInstance = domainInstanceToClone.getClass()。newInstance()
//返回用于检查属性的DefaultGrailsDomainClass(作为接口GrailsDomainClass)
GrailsClass domainClass = domainInstanceToClone.domainClass.grailsApplication.getDomainClass(newDomainInstance.getClass()。name)
def notCloneable = domainClass .getPropertyValue(notCloneable)
$ b $ for(DefaultGrailsDomainClassProperty prop in domainClass?.getPersistentProperties()){
if(notCloneable&& prop.name in notCloneable)
continue
if(prop.association){
if(prop.owningSide){
//我们必须深度克隆拥有的关联
if(prop.oneToOne){
def newAssociationInstance = deepClone(domainInstanceToClone? $ {prop.name})
newDomainInstance。$ {prop.name}= newAssociationInstance
} else {
$ b $ domainInstanceToClone。$ {prop.name} .each {associationInstance - > (newAssociationInstance)
newDomainInstance。addTo $ {prop.name.capitalize()}(newAssociationInstance)
}
} else {
if(!prop.bidirectional){
//如果关联不是拥有者或所有者,则我们可以做一个参考的浅表副本。
newDomainInstance$ {prop.name}= domainInstanceToClone。$ {prop.name}
}
// @@ JR
//是双向的并且不拥有。例如。克隆报告,belongsTo组织,其中有许多
// manyToOne。只需添加到拥有的对象集合。
else {
// println$ {prop.owningSide} - $ {prop.name} - $ {prop.oneToMany}
//返回
if(prop。 $ {prop.name}= domainInstanceToClone。$ {prop.name}
def owningInstance = domainInstanceToClone。$ {prop.name}$ {
$ b $ newDomainInstance。 b $ b //需要找到收藏。
String otherSide = prop.otherSide.name.capitalize()
// println otherSide
//owningInstance.\"addTo${otherSide}\"\"newDomainInstance
else if(prop.manyToMany){
//newDomainInstance.\"${prop.name}= [] as Set
domainInstanceToClone。$ {prop.name}。 {
//newDomainInstance.\"${prop.name}\".add(it)
}
}
else if(prop.oneToMany ){
domainInstanceToClone。$ {prop.name}。each {associationInstance - >
def newAssociationInstance = deepClone(associationInstance)
newDomainInstance。addTo $ {prop.name.capitalize()}(newAssociationInstance)
}
}
}
}
} else {
//如果属性不是关联,那么只需复制值
newDomainInstance。$ {prop.name}= domainInstanceToClone。$ {prop .name}
if(prop.name ==dateCreated|| prop.name ==lastUpdated){
newDomainInstance。$ {prop.name}= null
}
}
}
return newDomainInstance
}
clone()
methods in the corresponding domain classes.new
" rather than "super.clone(),"
so as soon as I thought about doing the same for my Grails domainclasses, I wondered how using super.clone()
to obtain a clone mightinteract with GORM
/ Hibernate persistence. In particular, I waswondering about the proper way to handle the implicit "id" property. IfI simply super.clone()
, do nothing further and later try to save()
thecloned instance, will it work properly (creating a new persistenceentry?) or will some kind of error or silent failure result?GormInstanceApi
which all domain implements it. : def cloneForDomains={def cloned=delegate.class.newInstance();
cloned.properties=delegate.properties;
return cloned;}
org.grails.datastore.gorm.GormInstanceApi.clone=cloneForDomains ;
clone
method such as save
, delete
.....Person p=Person.get(1);
Person cloned=p.clone();
cloned.id=null;
cloned.save();
grailsApplication.getDomainClasses().each{cls->
cls.metaClass.clone=cloneForDomains
}
grailsApplication.getDomainClasses().each{cls->
cls.metaClass.clone={
return deepClone(delegate);
}
}
deepClone
is a method as following: Object deepClone(domainInstanceToClone) {
//TODO: PRECISA ENTENDER ISSO! MB-249 no youtrack
//Algumas classes chegam aqui com nome da classe + _$$_javassist_XX
if (domainInstanceToClone.getClass().name.contains("_javassist"))
return null
//Our target instance for the instance we want to clone
// recursion
def newDomainInstance = domainInstanceToClone.getClass().newInstance()
//Returns a DefaultGrailsDomainClass (as interface GrailsDomainClass) for inspecting properties
GrailsClass domainClass = domainInstanceToClone.domainClass.grailsApplication.getDomainClass(newDomainInstance.getClass().name)
def notCloneable = domainClass.getPropertyValue("notCloneable")
for(DefaultGrailsDomainClassProperty prop in domainClass?.getPersistentProperties()) {
if (notCloneable && prop.name in notCloneable)
continue
if (prop.association) {
if (prop.owningSide) {
//we have to deep clone owned associations
if (prop.oneToOne) {
def newAssociationInstance = deepClone(domainInstanceToClone?."${prop.name}")
newDomainInstance."${prop.name}" = newAssociationInstance
} else {
domainInstanceToClone."${prop.name}".each { associationInstance ->
def newAssociationInstance = deepClone(associationInstance)
if (newAssociationInstance)
newDomainInstance."addTo${prop.name.capitalize()}"(newAssociationInstance)
}
}
} else {
if (!prop.bidirectional) {
//If the association isn't owned or the owner, then we can just do a shallow copy of the reference.
newDomainInstance."${prop.name}" = domainInstanceToClone."${prop.name}"
}
// @@JR
// Yes bidirectional and not owning. E.g. clone Report, belongsTo Organisation which hasMany
// manyToOne. Just add to the owning objects collection.
else {
//println "${prop.owningSide} - ${prop.name} - ${prop.oneToMany}"
//return
if (prop.manyToOne) {
newDomainInstance."${prop.name}" = domainInstanceToClone."${prop.name}"
def owningInstance = domainInstanceToClone."${prop.name}"
// Need to find the collection.
String otherSide = prop.otherSide.name.capitalize()
//println otherSide
//owningInstance."addTo${otherSide}"(newDomainInstance)
}
else if (prop.manyToMany) {
//newDomainInstance."${prop.name}" = [] as Set
domainInstanceToClone."${prop.name}".each {
//newDomainInstance."${prop.name}".add(it)
}
}
else if (prop.oneToMany) {
domainInstanceToClone."${prop.name}".each { associationInstance ->
def newAssociationInstance = deepClone(associationInstance)
newDomainInstance."addTo${prop.name.capitalize()}"(newAssociationInstance)
}
}
}
}
} else {
//If the property isn't an association then simply copy the value
newDomainInstance."${prop.name}" = domainInstanceToClone."${prop.name}"
if (prop.name == "dateCreated" || prop.name == "lastUpdated") {
newDomainInstance."${prop.name}" = null
}
}
}
return newDomainInstance
}