【问题标题】:GORM auto flush when request ends without calling save请求结束时 GORM 自动刷新而不调用 save
【发布时间】:2013-10-27 11:20:55
【问题描述】:

我准备了简单的控制器操作来测试与意外提交数据库更改相关的行为:

def testSimple() {
    Product p = Product.findById(1);

    p.name = "test doneee"

    //p.save flush:true

    respond p
}

即使save() 未被调用,更改也会保留在数据库中。如何避免在不调用save()的情况下保存实体?

【问题讨论】:

  • 只要不修改就不会保存。如果您不想修改实体,为什么要修改它?
  • 想象一下,在修改对象(如 POJO)之后,您执行一些暗示 save 不应该发生的逻辑。请不要否认这种琐碎的问题。
  • 然后回滚事务。

标签: hibernate grails grails-orm


【解决方案1】:

Grails 注册一个 OpenSessionInView 拦截器,它启动 Hibernate Session 和每个请求的开始,并在请求结束时刷新和关闭它。这主要是为了允许延迟加载的一对多实例和多对一集合按需加载。一个副作用是您所看到的,即使没有save() 调用,更改持久实例也会导致更改被推送到数据库。这是因为更改它会将其标记为脏,并且 Hibernate 在刷新期间会发现所有脏对象并将更改推送到数据库。

为避免此类更改被持久化,请使用 http://grails.org/doc/latest/ref/Domain%20Classes/discard.html 方法将其与 Session 分离。

附言不相关,但您应该使用get 而不是findById,因为get 做同样的事情,但缓存行为要好得多。

【讨论】:

    【解决方案2】:

    这会使您的操作顺序变成一场噩梦。 [查看此 SO 帖子][1] Grails GORM auto update issue

    它使在大型应用程序上下文中对对象使用 getPersistentValue() 方法变得可怕。如果链中某处有数据库调用,即使它完全不相关,您的持久值也会改变。

    我确实发现将数据库调用标记为只读可以防止触发自动保存。 例如在服务中

    import org.springframework.transaction.annotation.Transactional
    
      class TestService{
    
       @Transactional(readOnly = true)
       def queryDatabase(){
          //this operation won't trigger auto updates now, yay
       }
    
      }
    

    但并非所有情况都是只读的,如果另一个开发人员没有明确设置只读,那么在大上下文中,您的代码可能会再次被 ka-put。但这对你来说很重要,通过约定实现复杂性

    【讨论】:

      猜你喜欢
      • 2016-03-26
      • 2010-10-15
      • 2013-02-15
      • 1970-01-01
      • 1970-01-01
      • 2018-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多