如果我在Grails命令对象中使用GORM域对象,则命令对象会自动更改域对象,即使我没有调用save()方法。
我希望绑定到命令对象中的GORM对象,但不保存或提交对数据库的更改。如果我的控制器或我的服务抛出异常,我想要事务回滚。
我可以通过以下注释强制我想要的行为,但感觉就像我正在努力做到这一点。
Controller Class = @Transactional(readOnly = true)
Controller action method = @Transactional
Command Object Class = @Transactional(readOnly = true)
Service Class = @Transactional
我做错了什么,Grails域对象应该由命令对象自动提交,除非我添加所有这些注释?
答案 0 :(得分:1)
这不是命令对象特有的,它是控制器动作的一般特征。默认情况下,open-session-in-view模式处于活动状态,其中创建Hibernate会话并在操作运行之前绑定到线程本地,并在操作完成后刷新并关闭。从数据库中检索的任何持久实例(由于查询而显式,或者在数据绑定期间隐式)都将保持附加到打开会话,并在会话刷新时进行脏检查。任何已修改的实例都会将其更改与其他排队操作一起刷新,无论是否有save()
调用。
使整个方法(或类)具有事务性和只读性可能是过度的。更直接的方法是将实例检索为只读,例如,使用read()
代替get()
,在进行条件查询等时调用readOnly
方法,或者分离'通过在每个上调用discard()
方法修改实例。另一种选择是在动作结束时清除会话,因此无需自动刷新,例如。
AnyDomainClass.withSession { it.clear() }
请注意,以“只读”方式检索的实例'模式可以保持更改,但Hibernate不会自动为这些实例执行任何操作,只有在您明确调用save()
时才会发生。