在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()。
你怎么看?这是一个“正常”的行为,还是一个错误?我该如何解决这个问题?如果需要,我有一个简单的复制案例,有两个实体。
答案 0 :(得分:0)
我可能在这里遗漏了一些东西,但不是'discard'方法的全部目标,不应用更改,以及您在此处看到的内容(在验证的情况下不应用更改)错误)是合乎逻辑的?
答案 1 :(得分: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();
只是一个想法!