0

在 Grails 服务中,我基于外部列表创建/更新域实体。更新循环进行。如果输入文件中的行有效,则更新实体。否则,我存储错误的行号并处理下一个。

问题:当我在实体上调用 validate() 时,如果结果是false,则服务中完成的任何工作都会回滚,即使与验证无关,也没有可见异常。例如:

assert contact.firstName = 'Bruce'
contact.firstName = 'John'
assert contact.save()
...
company.vat = 'bogus'
if (!company.validate()) {
    log.error "bogus"
    company.discard()
} else {
    assert company.save()
}
log.debug "done"

如果公司不验证,我的日志将显示“伪造”和“完成”。联系人名字将'Bruce'在数据库中,而不是'John'.

替代版本:如果我不打电话company.validate(),联系人的名字会更新。

在这个阶段,我怀疑 Grails 将我的公司实例附加到 validate() 调用上,当它意识到验证没有通过时,尽管进行了 discard() 工作,但它注定了该事务。

从 validate() 语义和它的 javadoc(“验证实例”)来看,我没想到会有任何副作用,无论验证是否失败,或者我什至是否调用 validate()。

你怎么看?这是“正常”的行为,还是错误?我该如何解决这个问题?

如果需要,我有一个带有两个实体的简单复制案例。

4

2 回答 2

0

无法在此设置上对其进行测试,但您能否在服务中设置 transactional = false,处理所有对象(在一个列表中添加正确验证的对象并将失败的对象保存/记录到其他地方),然后最后保存“好" 使用 withTransaction 的对象列表?就像是:

static transactional = false
def sessionFactory
List<Company> validCompanies = []
for(Company company: listOfCompaniesToValidate) {
    if (!company.validate()) {
        log.error "bogus"
    } else {
        validCompanies.add(company)
    }
}
Company.withTransaction {
    for (Company validCompany: validCompanies)
        validCompany.save()
    }
    validCompanies.clear()
}
sessionFactory.getCurrentSession().clear();

只是一个想法!

于 2013-01-14T18:23:54.343 回答
0

我可能在这里遗漏了一些东西,但“丢弃”方法的全部目标不是不应用更改,您在这里看到的(在验证错误的情况下不应用更改)是合乎逻辑的吗?

于 2013-01-14T13:59:04.627 回答