Grails:即使事务已经失败,我想继续验证时如何构建事务

时间:2012-02-09 02:46:30

标签: grails transactions

我的用户正在上传csv或xls或其他任何内容,每一行都将成为我保存的域对象的实例。如果任何一行失败,我希望整个事情回滚,但我也想为以后失败的任何行返回错误。让我们举个例子:

域类:

MyDomainClass{
  String fieldOne
  BigDecimal fieldTwo
}

输入:

ThisLineWorks,4.4
ThisLineFails,BecauseOfThis
How would I also get an error, for this line as well considering the last one would have rolled back the transaction already?

幻想输出:

OK|ThisLineWorks,4.4
field 2 isn't a number|ThisLineFails,BecauseOfThis
field 2 isn't a number|How would I also get an error, for this line as well considering the last one would have rolled back the transaction already?

2 个答案:

答案 0 :(得分:2)

这就是我的想法:

1。设置一个标记ALL CLEAR的标志,如果一切都清楚,则在末尾手动提交事务。

2。在单独的事务中提交每一行,捕获失败行的错误并跳过失败。

答案 1 :(得分:2)

您可以验证对象而无需保存它们:(http://grails.org/doc/2.0.x/guide/validation.html#validatingConstraints)。因此,在服务中,您可以创建所有对象,然后验证所有对象,然后保存所有对象。类似于:

def serviceMethod(data) {
    def listOfObjects = createObjectsFromData(data)
    listOfObjects*.validate()
    def anErrorOccurred = listOfObjects.find {it.hasErrors()} != null
    if(anErrorOccurred) {
        return listOfObjects
    }
    listOfObjects*.save(validate: false) //you could use the validate:false or leave it out.  I figure since we've already validated that you could do without re-validating.
}

这样您就可以收集所有错误,而不必担心回滚事务。此设置的问题是您将创建N个对象并保留所有对象。如果您的文件长度超过100k行(对于您将开始受到影响的位置稍微有点教育),那么这可能会导致一些性能问题。如果您不喜欢上述方法,则可以手动处理事务: (http://grails.org/doc/2.0.x/ref/Domain%20Classes/withTransaction.html

def serviceMethod(data) {
    MyDomainClass.withTransaction { status ->
        def listOfObjects = []
        data.each {
            def domainObject = createObjectFromData(it)
            lisOfObjects << domainObject.save()
        }
        def anErrorOccurred = lisOfObjects.find {it.hasErrors()} != null
        if(anErrorOccurred) {
           status.setRollbackOnly()  //will roll back all of the transactions surrounded by the .withTransaction {}
        }
    }
}

你仍然坚持这里的所有对象(因为你想要检索发生的所有错误)。我可以想到避免持有所有对象的一种方法是一次创建一个对象并逐个验证它们在适用时向列表添加错误,但是你必须重新创建所有对象当他们都通过验证时,这似乎也没有效率。