我有一台Grails 2.4.4控制器:
class FooController {
def fooService
@Transactional
def save(Foo foo) {
def duplicateFoos = fooService.duplicateFoos(foo)
if (duplicateFoos) {
flash.error = "Duplicate foos exist: $duplicateFoos"
render(model: foo, view: 'create')
} else { /* ... */ }
}
服务也很简单
@Transactional
class FooService {
def duplicateFoos(Foo foo) {
log.info(foo) // here foo has no ID
JobAssignment.findAllBySomeProperty(foo.someProperty)
log.info(foo) // here new ID is assigned to foo
}
}
Foo到达未保存且没有ID进入duplicateFoos方法,但在执行后,它突然带有ID并保存在数据库中(从日志语句中可以看出)。
我有
dataSource {
flush.mode = 'manual'
}
DataSource.groovy
中的。
我手动尝试
sessionFactory.currentSession.transaction.rollback()
或
sessionFactory.currentSession.transaction.rollback()
sessionFactory.currentSession.transaction.begin()
FooController
中的。在这种情况下,ID仍会在findAllBySomeProperty
阶段分配(不确定原因),但它不会持久保存到数据库。但是,我得到org.hibernate.TransactionException: Transaction not successfully started
。
我还尝试手动设置sessionFactory.currentSession.flushMode = FlushMode.MANUAL
,虽然它似乎有助于这个特定的位置(没有分配新ID),但其他后来的代码并没有调用save
(或者任何)对象仍然保存它。我也不认为在每个交易方法的开头都有flushMode = MANUAL
是一个很好的解决方案。
我现在只是抛出一个Exception
- 确保没有任何东西被保存。这显然不是一个好的解决方案,因为我需要重定向回到表单。
那么当我打电话给.save
时,我怎样才能强制保存对象?
或者,如果无法做到这一点,如何在仍然能够重定向到某个屏幕的同时干净地回滚事务?
P.S。我回顾了一堆可能相关的Grails JIRA,但我没有找到解决问题的方法:
@BurtBeckwith,是的,Foo belongsTo
Bar和Bar hasMany
Foo-s(两者都是标准的Grails域对象)。
但是,我不会在这些方法中操作Bar-s。我所做的只是:
def createForBar(Long barId) {
Bar bar = Bar.findById(barId)
Foo foo = new Foo(bar: bar)
render(view: 'create', model: createModel(foo))
}
然后create
表单有一个按钮,可以调用前面提到的save
。
@JeffScottBrown - 它是POST
,创建新的id
时没有Foo
参数。
我通过了
<input type="hidden" name="bar.id" value="${fooInstance?.bar?.id}"/>
虽然。