为什么Grails命令对象默认提交对域对象的更改?

时间:2016-05-16 23:22:11

标签: grails gorm

如果我在Grails命令对象中使用GORM域对象,则命令对象会自动更改域对象,即使我没有调用save()方法。

我希望绑定到命令对象中的GORM对象,但不保存或提交对数据库的更改。如果我的控制器或我的服务抛出异常,我想要事务回滚。

我可以通过以下注释强制我想要的行为,但感觉就像我正在努力做到这一点。

Controller Class = @Transactional(readOnly = true)
Controller action method = @Transactional
Command Object Class = @Transactional(readOnly = true)
Service Class = @Transactional

我做错了什么,Grails域对象应该由命令对象自动提交,除非我添加所有这些注释?

1 个答案:

答案 0 :(得分:1)

这不是命令对象特有的,它是控制器动作的一般特征。默认情况下,open-session-in-view模式处于活动状态,其中创建Hibernate会话并在操作运行之前绑定到线程本地,并在操作完成后刷新并关闭。从数据库中检索的任何持久实例(由于查询而显式,或者在数据绑定期间隐式)都将保持附加到打开会话,并在会话刷新时进行脏检查。任何已修改的实例都会将其更改与其他排队操作一起刷新,无论是否有save()调用。

使整个方法(或类)具有事务性和只读性可能是过度的。更直接的方法是将实例检索为只读,例如,使用read()代替get(),在进行条件查询等时调用readOnly方法,或者分离'通过在每个上调用discard()方法修改实例。另一种选择是在动作结束时清除会话,因此无需自动刷新,例如。

AnyDomainClass.withSession { it.clear() }

请注意,以“只读”方式检索的实例'模式可以保持更改,但Hibernate不会自动为这些实例执行任何操作,只有在您明确调用save()时才会发生。