I have a strange situation which appears to indicate a GORM cacheing problem
//begin with all book.status's as UNREAD
Book.list().each { book.status = Status.READ ; book.save() }
println (Book.findAllByStatus (Status.READ)) //will print an empty list
println (Book.list().findAll (it.status == Status.READ)) // will print all books
I cannot understand why the last two queries could return different results.
However if I make the following modification of book.save(flush:true). Both of the println statements will return all books.
I was under the impression that this was not necessary within a single application.
For reference I’m using
- DB: mysql
- Groovy: 1.7.10
- Grails: 1.3.7
@Hoàng Long
My problem is demonstrated below, suppose action1/action2 are both called many many times, in no particular pattern
def action1 = {
Foo foo = Foo.get(params.id)
//... modify foo
foo.save() //if I flush here, it will be inefficient if action1 is called in sequence
}
def action2 = {
//if I flush here, it will be inefficient if action2 is called in sequence
List<Foo> foos = Foo.findAllByBar (params.bar)
//... do something with foos
}
One solution would be to have a flag which is is set by action1 and used by action2 to flush if necessary. My issue is that this is an overly complex solution, which is not scalable as the complexity of DB calls increases.
boolean isFlushed = true
def action1 = {
Foo foo = Foo.get(params.id)
//... modify foo
foo.save()
isFlushed = false
}
def action2 = {
if (!isFlushed) {
//flush hibernate session here
}
List<Foo> foos = Foo.findAllByBar (params.bar)
//... do something with foos
}
In your case, the first statement return empty list because it reads data from the database, but the data isn’t there yet.
It’s how Hibernate works: When you call save with
(flush: true), it will flush the Hibernate session, persistent all data in session to database immediately. If not using(flush:true), the data is only recorded in Hibernate session and only get persisted in database when Hibernate session is flushed. The time to flush the session is automatically determined by Hibernate to optimize the performance.Generally, you should let Hibernate do the work for you (for optimization sake) – unless you want the data are persisted right away.
According to Peter Ledbrook:
From GORM Gotchas – part 1
UPDATE: to be clear about how to flush the session one time after all the object get saved: