Grails:当我想在事务已经失败后继续验证时如何构建事务

发布于 2025-01-03 20:18:43 字数 667 浏览 2 评论 0原文

我的用户正在上传 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?

Fantasy 输出:

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?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

寒冷纷飞旳雪 2025-01-10 20:18:43

您可以验证对象而无需保存它们:( 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 {}
        }
    }
}

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

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.

琴流音 2025-01-10 20:18:43

这就是我的想法:

1 。设置一个表示“全部清除”的标志,如果一切都清除,则在最后手动提交事务。

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

here is what i am thinking:

1 . Set a flag that signals ALL CLEAR and commit the transaction manually at the end if all is clear.

or

2 . Commit each line in a separate transaction capturing errors of failed lines and skipping over failures.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文