Grails:即使事务已经失败,如何继续验证,如何构建事务 [英] Grails: how to structure transactions when I want to continue validating even after the transaction has already failed

查看:105
本文介绍了Grails:即使事务已经失败,如何继续验证,如何构建事务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

域类:

  MyDomainClass {
String fieldOne
BigDecimal fieldTwo
}

输入:

  ThisLineWorks,4.4 
ThisLineFails,BecauseOfThis
我也会得到一个错误,对于这一行以及考虑最后一个会回滚事务了吗?

幻想输出:

 确定| ThisLineWorks,4.4 
字段2不是数字| ThisLineFails,BecauseOfThis
字段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 $ b $ if(anErrorOccurred){
return listOfObjects
}
listOfObjects * .save(validate:false)//你可以使用validate:false或者不用。我认为,因为我们已经验证过你不需要重新验证。
}

这样你就可以收集你所有的错误,而不必担心滚动支持交易。这个设置的问题是您将创建N个对象并保留所有对象。如果您的文件长度超过10万行(稍微有教育意义的猜测会让您开始受到影响),那么这可能会导致一些性能问题。如果您不喜欢上述方法,则可以手动处理交易:
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()//将回滚所有由.withTransaction {}
}
}
}

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


My users are uploading a csv or xls or whatever and each line is going to be an instance of a domain object I save. If any of the lines fail I want the whole thing rolled back, but I also want to return errors for any lines that will fail later. Let's make an example:

Domain class:

MyDomainClass{
  String fieldOne
  BigDecimal fieldTwo
}

Input:

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?

Fantasy Output:

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?

解决方案

You can validate the objects without having to save them: ( http://grails.org/doc/2.0.x/guide/validation.html#validatingConstraints). So in a service you can create all of the objects, then validate all of the objects, then save all of the objects. Something similar to:

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.
}

This way you can collect all of your errors and not have to worry about rolling back the transaction. Problem with this setup is you'll be creating N number of objects and holding onto all of them. If your file is longer than 100k rows (a slightly educated guess on where you'll start to suffer) then this might cause some performance issues. If you don't like the above method you could handle the transaction manually: ( 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 {}
        }
    }
}

You're still holding onto all of the objects here (since you want to retrieve ALL errors that occur). One way I can think of to avoid holding onto all of the objects would be to create the objects one at a time and validate them one by one adding errors to a list when applicable, but then you'd have to recreate all of the objects when they all pass validation which doesn't seem very efficient either.

这篇关于Grails:即使事务已经失败,如何继续验证,如何构建事务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆