How can I duplicate a domain object in Grails?

自作多情 提交于 2019-12-30 18:24:20

问题


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

I realize I could create a new record, and then iterate over each of the fields copying the data field-by-field - but I figured there must be an easier way to do this...

In Rails there is a simple 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?


回答1:


There is not. It has been requested http://jira.grails.org/browse/GRAILS-3532. Someone has added some code to that issue that might be helpful to you though.




回答2:


I've adapted a piece of code that make the deep clone of domain classes. I've been using in my system and it works very well (in most of cases). The code bellow is an adaptation found in http://grails.1312388.n4.nabble.com/Fwd-How-to-copy-properties-of-a-domain-class-td3436759.html

In my application the user has the option to saveAs some type of objects and I use the deepClone to do that.

You can specify "not cloneable" properties. For that you need to specify a static map (in your class) with the properties that you don't 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. 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
}


来源:https://stackoverflow.com/questions/17614791/how-can-i-duplicate-a-domain-object-in-grails

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!