2

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

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

    p.name = "test doneee"

    //p.save flush:true

    respond p
}

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

4

2 回答 2

9

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

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

ps 不相关,但您应该使用get代替findById, 因为get做同样的事情但有更好的缓存行为。

于 2013-10-27T18:07:44.653 回答
2

这会使您的操作顺序成为一场噩梦。[查看此 SO 帖子][1] Grails GORM 自动更新问题

它使在大型应用程序上下文中对对象使用 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-09-23T20:49:08.300 回答