Grails: Prevent cascading association between two domain classes with multiple relationships

人盡茶涼 提交于 2020-01-11 14:05:07

问题


Consider two domain classes; Job and Quote.

A Job has many Quotes but a Job also has an accepted quote. The accepted quote is nullable and should only be set once a particular Quote has been accepted by a user. I have the relationships mapped as follows (simplified for the purpose of illustration).

class Job {
    String title
    Quote acceptedQuote   
}

class Quote {
    Job job
    BigDecimal quoteAmount 
}

The resultant tables are exactly what I require (at least aesthetically) but the problem arises when I go and save a Quote. The Quote is saved successfully with a jobId as per the logic in my code but unfortunately the quote's id gets saved in the Job table as the acceptedQuote. Is there anyway to block this cascading association? The code that persists the Quote is fairly basic and looks something like the following;

def quoteInstance = new Quote(job: jobInstance, quoteAmount: amount)
if (quoteInstance.save(flush: true)) {
   render view: 'show', model: [quoteInstance: quoteInstance]
   break
}

Obviously the jobInstance is passed to the Quote constructor to save an association in the Quote table but I do not know how to prevent the quote Id saving to the job table as the accepted quote. Maybe the GORM strategy I am using will not satisfy these requirements?

Any help would be much appreciated.


回答1:


This may not be what you are looking for but I would actually model this a little differently - I would have an accepted flag in the Quote domain:

class Job {
    String title
    static hasMany = [quotes: Quote]
}

class Quote {
    static belongsTo = [job: Job]
    BigDecimal quoteAmount
    Boolean accepted
}

Then your persistence could look like this:

jobInstance.addToQuotes(new Quote(quoteAmount: 123.34, accepted: false)) //or true

and no worries regarding your original problem.

You could also add a transient and its getter to the Job class to get the accepted Quote

class Job {
    String title
    static hasMany = [quotes: Quote]

    static transients = ['acceptedQuote']

    Quote getAcceptedQuote() {
        return Quote.findByJobAndAccepted(this, true)
    }

}



回答2:


Grails/GORM has made the associations simpler by following the methodology of convention over configuration and making things more verbose.

What do you think of the below structure of the domain classes?

class Job {
    String title
    static hasMany = [quotes: Quote]//Job has many Quotes. Note: Accepted Quote is one of them.
}

class Quote {
    BigDecimal quoteAmount
    Boolean isAccepted

    static belongsTo = [job: Job]//Quote always belongs to a Job.
    //When a Job is deleted, quote is also cascade deleted.
}

Now if you create your quote like below then everything should work perfectly:

def job = new Job(title: "Test Job").save()
//Just adding a quote
def quoteInstance = new Quote(quoteAmount: amount)
job.addToQuotes(quoteInstance)
job.save()

//Now accepting that quote
quoteInstance.isAccepted = true
job.save()

Done.

Do we need an acceptedQuote reference in Job? No
How to get to the acceptedQuote?

def acceptedQuote = job.quotes.find{it.isAccepted}




回答3:


Take a look at hasOne and belongsTo association configuration. Take a look at cascade to learn more about cascade behaviour configuration.



来源:https://stackoverflow.com/questions/16471962/grails-prevent-cascading-association-between-two-domain-classes-with-multiple-r

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