gpt4 book ai didi

Grails 事务和 session

转载 作者:行者123 更新时间:2023-12-02 14:06:10 25 4
gpt4 key购买 nike

假设您在 Grails 2.5.5 应用程序中有以下 Controller :

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 之后,您手动将该对象的标题编辑为“哈利波特与 chalice ”火”,我预计:

  • bookService.method()中的findById(4)都是读取同一个值,毕竟它们是在同一个事务中隔离执行的,如果那个事务在那个状态下读取它,第二个应该也读取它.
  • 在 Controller 中执行的 findById(4) 已在手动更新后看到对象的新状态。毕竟,第一个事务已经提交,第二个发现,即使在服务之外完成,也应该创建一个新事务。

但是,输出将始终是处于与开始时相同状态的对象。

更新:输出为:

The Lord Of The Rings
The Lord Of The Rings
The Lord Of The Rings

在任何情况下,如果您修改 Controller ,以便:

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

谁能解释一下原因:

  1. 仅在读取某个状态的对象的事务之外不足以读取新数据;
  2. 即使强制执行新事务也不足以读取具有最新状态的对象;
  3. 为什么新类(class)允许我们这样做。

最佳答案

首先 Book bako = Book.findById(4) findById 应该在极少数情况下使用引用 Book.get(1L) Book.load(1L) Book.read(1L)

当您本可以运行 .get

时,您正在启动查询以查找 id

实际问题

说多了,再多的服务也是事务性的。如果您决定手动使用 mysql 更新数据库。您将破坏休眠缓存。您可以尝试禁用 - 首先/second level cache .首先是如果您在域类映射中声明了缓存。

这确实是不明智的,而且会影响应用。事实上,交易服务应该为您进行更新。如果需要手动更新数据库。停止应用程序更新/启动应用程序。就这么简单

我一直在尝试使用示例项目来插入您尝试此场景,这是有原因的。

为什么?因为它有助于回答任何猜测。我已经复制了您的示例项目,并在演示中添加了一些实际记录更新。 https://github.com/vahidhedayati/grails-transactions

我还对您的版本提出了拉取请求,以便您可以合并它并在本地进行测试。

基本上 flush:true 不需要。 .get(id) 不需要。

正如您从下面的结果中看到的那样,在方法 1 的 .save() 之后的服务中,结果已更新。在 Controller 中,它在服务返回后使用 method() 返回了正确的结果。

-- transactions.Book : 1 1 added
| Server running. Browse to http://localhost:8080/transactions
2016-09-05 18:12:48,520 [http-bio-8080-exec-4] DEBUG hibernate.SQL - select book0_.id as id1_0_0_, book0_.version as version2_0_0_, book0_.title as title3_0_0_ from book book0_ where book0_.id=?
--method1: before update: ------------------------------> TITLE_SET_BY_BOOTSTRAP
--method1 before get: ---------------------------------> New title from method1
method1 after get: ----------------------------------> New title from method1
2016-09-05 18:12:48,618 [http-bio-8080-exec-4] DEBUG hibernate.SQL - update book set version=?, title=? where id=? and version=?
After service1 call 1 New title from method1
--method2 update: ------------------------------> New title from method1
2016-09-05 18:12:48,687 [http-bio-8080-exec-4] DEBUG hibernate.SQL - update book set version=?, title=? where id=? and version=?
--method2 before get: --------------------------> New title from method2
method2 after get: ----------------------------> New title from method2
After service call 2 New title from method2
--method3 before update: ---------------------------> New title from method2
2016-09-05 18:12:48,795 [http-bio-8080-exec-4] DEBUG hibernate.SQL - update book set version=?, title=? where id=? and version=?
--method3 updated before get: -------------------------> New title from method3
--method3 after get: -----------------------------------> New title from method3
After service call 3 New title from method3

在审查了很久以前的用户问题并了解他们正在手动更新数据库记录之后,他们希望屏幕显示相同的结果。

简而言之,如果您没有在应用程序中启用缓存,那么它应该可以正常工作。如果您启用了某种形式的 Hibernate 缓存或 ehcache,那么您很可能会查看一些缓存对象。我曾建议重新启动应用程序以确保您拥有最新的。但如果你只是:

包装一个

DomainClass.withNewTransaction { 
//get the latest copy
DomainClass clazz = DomainClass.get(recordId)
println "-- ${clazz.value}"
}

这应该确保您从数据库中获得最新的,它不会提高速度,但如果您期望手动更新数据库,您始终可以确保最新的在上面..

关于Grails 事务和 session ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39296682/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com