问题
I have prepared simple controller action to test behaviour related with unexpected commiting changes to datatbase:
def testSimple() {
Product p = Product.findById(1);
p.name = "test doneee"
//p.save flush:true
respond p
}
The changes are persisted in database even the save()
has not been called. How to avoid saving entity without calling save()
?
回答1:
Grails registers an OpenSessionInView interceptor which starts a Hibernate Session and the beginning of each request, and flushes and closes it at the end of the request. This is primarily done to allow lazy-loaded one-to-many instances and many-to-one collections to load on demand. One side effect is what you're seeing, that changing a persistent instance causes the changes to get pushed to the database even without a save()
call. This is because changing it marks it dirty, and Hibernate discovers all dirty objects during the flush and pushes the changes to the database.
To avoid changes like this from being persisted, use the http://grails.org/doc/latest/ref/Domain%20Classes/discard.html method to detach it from the Session.
p.s. Unrelated, but you should use get
instead of findById
, since get
does the same thing but has much better caching behavior.
回答2:
This can make your order of operations a nightmare. [See this SO post][1] Grails GORM auto update issue
It makes using the getPersistentValue() method on an object scary in a large application context. If there is a database call somewhere in the chain, even if it is totally unrelated, your persisted values will change.
I did find that marking database calls as readonly prevents trigger of auto save. For example in a a service
import org.springframework.transaction.annotation.Transactional
class TestService{
@Transactional(readOnly = true)
def queryDatabase(){
//this operation won't trigger auto updates now, yay
}
}
But not all cases would be read only, and again in a large context your code could go ka-put if another developer doesn't explicitly set readonly. But that's grails for you, complexity through convention
来源:https://stackoverflow.com/questions/19617470/gorm-auto-flush-when-request-ends-without-calling-save