【发布时间】:2016-09-02 16:07:29
【问题描述】:
假设您在 Grails 2.5.5 应用程序中有以下控制器:
def index() {
bookService.method()
Book bako = Book.findById(4)
System.out.println(bako.title);
}
在 bookService 内部(使用 Grails 默认事务管理),您有以下方法:
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);
}
}
而且您的数据库确实有一本 ID 为 4 的书,名为“指环王”。
如果您随后在所有 System.out.println() 上设置断点,并且在执行第一个 findById 之后,您手动将该对象的标题编辑为“哈利波特与火”,我预计:
- 在 bookService.method() 中的 findById(4) 都读取相同的值,毕竟它们是在同一个事务中隔离执行的,如果该事务在该状态下读取它,则第二个也应该读取它.
- 在手动更新后,控制器中执行的 findById(4) 已经看到对象的新状态。毕竟,第一个事务已经提交,第二个查找,即使在服务之外完成,也应该创建一个新事务。
但是,输出将始终是处于与开始时相同状态的对象。
更新:输出为:
The Lord Of The Rings
The Lord Of The Rings
The Lord Of The Rings
在任何情况下,如果您修改控制器,以便:
def index() {
bookService.method()
Book.withNewTransaction {
Book bako = Book.findById(4)
System.out.println(bako.title);
}
}
结果还是一样。
更新:输出为:
The Lord Of The Rings
The Lord Of The Rings
The Lord Of The Rings
仅当您将其修改为:
def index() {
bookService.method()
Book.withNewSession {
Book bako = Book.findById(4)
System.out.println(bako.title);
}
}
是否会出现正确的行为。
更新:输出为:
The Lord Of The Rings
The Lord Of The Rings
Harry Potter and the Goblet of Fire
谁能解释一下原因:
- 仅仅在事务之外读取处于某种状态的对象是不足以读取新数据的;
- 即使强制执行新事务也不足以读取具有最新状态的对象;
- 为什么新会话允许我们这样做。
【问题讨论】:
标签: grails grails-orm