具有链接调用的Grails Service类的事务行为

时间:2011-02-14 13:04:44

标签: database grails transactions groovy service

我正在解析我的应用程序中的xml文件,我正在努力设计这个。

我允许上传我们的xml架构的“不完整”树,这意味着只要树形成良好,它就可以是根节点的任何子子节点。大多数节点都有子节点,只包含一些文本(属性),但我的小xml结构示例中没有包含任何这些节点。

<root>
    <childFoo>
        <childBar>
        </childBar>
    </childFoo>
</root>

允许任何一个节点。 现在,我设计了一个XmlInputService,它具有解析各个节点的方法。我只是在控制器中检测到它是什么类型的节点,并相应地将其交给服务方法。

因此,为了保持我的代码干爽和好,我在更高级别重用我的方法。如果我将Root类型的文档传递给服务,它将解析root中直接属于root的任何字段,并将子节点(表示我的域类结构中的子节点)传递给适当的解析方法。服务。

现在,如果用户上传包含约束违规的xml,即具有非唯一名称的元素等,我显然想要回滚它。

让我说我调用parseRoot()并向下调用parseChildFoo()。

在那里我为那里的每个Bar孩子调用parseChildBar()。如果其中一个Bar子项由于约束或其他原因无法验证,我显然希望将事务的回滚级联到parseFoo()。

我将如何实现这一目标?

2 个答案:

答案 0 :(得分:1)

对域对象制定这些有效性规则验证约束。

当save()违反约束时,抛出异常并在顶层解析级别捕获它,然后回滚整个事务。 喜欢:

meServiceMethod() {
    ...
    FooDomainClass.withTransaction { status ->
        try {
            parseRoot(xml)
        } 
        catch (FooBarParentException e) {
            status.setRollbackOnly()
            // whatever error diagnostics
        }
    }
    ...
}

或者你可以简单地让异常飞出服务方法到控制器 - 默认情况下服务方法是事务性的。

答案 1 :(得分:1)

如果你有一个grails服务,它有一个负责解析的方法,你应该抛出一个从你的服务扩展java.lang.RuntimeException的异常,这样就可以告诉用户他们需要修改他们的xml。因此,您的控制器将捕获该异常并为用户提供有意义的错误消息

每当从服务方法抛出runtimeexception时,Grails / Spring都会自动完成所有数据库修改的回滚。

我在Victor的回答中描述的方法的优点是,您不必编写任何代码来让事务在发生故障时回滚。 Grails会为你做的。 IMO,在服务方法中使用withTransaction闭包没有任何意义。

More info here