How can I duplicate a domain object in Grails?

I want to make a copy of a domain object. What is the easiest way to do this?

I understand that I can create a new record and then iterate over all the fields, copying the data field by field, but I decided that there should be an easier way to do this ...

Rails has an easy way to do this:

#rails < 3.1 new_record = old_record.clone #rails >= 3.1 new_record = old_record.dup 

Is there any equivalent in Grails?

+7
grails grails-domain-class
source share
2 answers

Not. It was requested by http://jira.grails.org/browse/GRAILS-3532 . Someone added some code to this question that may be useful to you.

+4
source share

I adapted a piece of code that makes a deep clone of domain classes. I use on my system and it works very well (in most cases). The code below is the adaptation found at http://grails.1312388.n4.nabble.com/Fwd-How-to-copy-properties-of-a-domain-class-td3436759.html

In my application, the user has the ability to save as some type of object, and I use deepClone for this.

You can specify non-clonable properties. To do this, you need to specify a static map (in your class) with properties that you do not want to clone, for example:

 static notCloneable = ['quoteFlows','services'] static hasMany = [quotePacks: QuotePack, services: Service, clients: Client, quoteFlows: QuoteFlow] static 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. Eg 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 } 
+8
source share

All Articles