Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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 } 
like image 459
Akusete Avatar asked Jun 09 '11 06:06

Akusete


1 Answers

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.

like image 171
dsharew Avatar answered Sep 20 '22 14:09

dsharew