【问题标题】:Grails flush: true inside Domain.withTransaction {} closureGrails flush: true inside Domain.withTransaction {} 闭包
【发布时间】:2019-09-20 19:44:49
【问题描述】:

This 文章内容如下:

Product.withTransaction{
    product.status = "ACTIVE"
    product.save(flush:true) //without this line the total number will be all of them but this one
    Product.countByStatus("ACTIVE")
}

不清楚的部分是以下注释:

如果没有这一行,总数将是所有这些,但这一行

以及上面代码后面的文章中的解释:

在没有强制flush:true的前面代码中,我们会省略我们在交易中保存的产品。

根据我的理解,如果我们调用product.save()(不刷新),product 实例应该附加到 Hibernate 会话,成为一个persistent 实体,它应该包含在Product.countByStatus("ACTIVE") 返回的数字中事务与我们保存产品的地方相同,即使指令未刷新到数据库,休眠会话也包含该已保存产品的信息。

【问题讨论】:

    标签: hibernate grails grails-orm


    【解决方案1】:

    通常在整个事务块(withTransaction{}withSession{} 或声明性分界)完成后刷新 DB-session。

    flush:true 使会话立即刷新。这意味着如果您调用product.save()count*() 方法会在会话刷新到数据库之前返回数据。如果您在事务后调用count*(),您会得到相同的行为:

    Product.withTransaction{
        product.status = "ACTIVE"
        product.save()
    }
    // here the TX shouldv'e been committed already
    Product.countByStatus("ACTIVE")
    

    【讨论】:

    • 同意,在我的场景中,如果我们省略 flush:true,那么 count*() 方法将在会话刷新之前返回,但在我的理解中,count*() 方法应该看到该会话包含一个产品status= "ACTIVE" 并且应该在返回的结果中包含该产品,即使会话尚未刷新到数据库。换句话说,count*() 查询不应该只检查已经刷新到 db 的记录,还应该检查 session 的内容,并从两个源返回合并的结果。如果我错了,请纠正我
    • 是的,你错了 :) session 中的对象是基于 id 使用的。它们主要用于优化引用解析,例如a.b.c,以便引用的实例仅在会话中加载一次。这就是为什么count*()-like 方法不能使用会话到merge 结果
    • 哦,我明白了。关于同一事务中的任何后续查询何时会或不会同时考虑资源(数据库和未刷新的会话数据)的任何有用资源/文档?
    • “关于同一事务中的任何后续查询何时会或不会同时考虑资源(数据库和未刷新的会话数据)的任何有用资源/文档?” - 这里有很多因素。某些行为取决于您使用的事务隔离级别以及数据存储的类型。
    • @JeffScottBrown 我在询问同一事务中的后续查询,例如在调用product.save()(不刷新)后的示例中的count*() 方法,在这种情况下事务隔离级别无关紧要。需要了解同一事务中的哪些查询可以或不可以在返回结果中考虑未刷新的会话数据
    猜你喜欢
    • 2017-12-31
    • 1970-01-01
    • 1970-01-01
    • 2019-04-19
    • 1970-01-01
    • 2021-03-17
    • 1970-01-01
    • 1970-01-01
    • 2014-11-14
    相关资源
    最近更新 更多