Imagine you have the following controller in a Grails 2.5.5 application:
def index() {
bookService.method()
Book bako = Book.findById(4)
System.out.println(bako.title);
}
And inside the bookService (with Grails default transaction management) you have the following method:
class BookService
def method() {
Book bako = Book.findById(4)
System.out.println(bako.title);
// MANUAL UPDATE OF DB HAPPENS HERE
Book bako = Book.findById(4)
System.out.println(bako.title);
}
}
And that your db does have a Book with id 4 called "The Lord of The Rings".
If you then set breakpoints on all System.out.println() and, after the first findById has been executed, you manually edit the title of that object to "Harry Potter and the Goblet of Fire", I expected:
- Both findById(4) in bookService.method() to read the same value, after all, they were performed in isolation in the same transaction, and if that transaction read it in that state, the second one should read it too.
- The findById(4) performed in the controller to already see the new state of the object, after the manual update. After all, the first transaction has already commited, and this second find, even if done outside a service, should create a new transaction.
However, the output will always be the object in the same state it was at the beginning.
Update: The output is:
The Lord Of The Rings
The Lord Of The Rings
The Lord Of The Rings
If, in any case, you modifiy the controller, in order to:
def index() {
bookService.method()
Book.withNewTransaction {
Book bako = Book.findById(4)
System.out.println(bako.title);
}
}
The result is still the same.
Update: The output is:
The Lord Of The Rings
The Lord Of The Rings
The Lord Of The Rings
Only if you modify it to:
def index() {
bookService.method()
Book.withNewSession {
Book bako = Book.findById(4)
System.out.println(bako.title);
}
}
does the correct behavior ensue.
Update: The output is:
The Lord Of The Rings
The Lord Of The Rings
Harry Potter and the Goblet of Fire
Can someone explain me why:
- Just being outside the transaction that read an object in a certain state is not enough to read fresh data;
- Even forcing a new transaction is not enough to read the object with its most up to date state;
- Why is the new session what allows us to do so.