Do I ever need to explicitly flush GORM save calls in grails?

Akusete picture Akusete · Jun 9, 2011 · Viewed 32.9k times · Source

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
}

Answer

dsharew picture dsharew · Feb 3, 2015

Do I ever need to explicitly flush GORM save calls in grails?

In short Yes!, if you want to use the object immediately as you are doing in your code.

I faced same problem, so this is the picture I got after reading some refs.

This is hibernate session issue.
Hibernate session is created when controller action is called and ends when the action returns ( or dies with error early). If a code is not calling any transactional code Hibernate's db interaction can be depicted like this:
Assume the entry action name is actionName and call to the action completes without any error.

NB:The middle bar ( 2nd level cache is disabled) because there is no any transactional code. without transaction without error

if the above same code has error:

without transaction with error

But if your action is calling transactional method or is creating inline transaction with withTransaction ( and assume the call to the action completed without any error). with transaction without error

If the above code has an error: with transaction with error

I hope it helps, but if I made any error or missed to include big point , comment me I will update my pics.