2011-02-14 65 views
2

我正在解析我的应用程序中的xml文件,我在如何设计这个问题上苦苦挣扎了一下。带链接调用的Grails服务类的交易行为

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

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

这些节点中的任何一个都是允许的。 现在,我设计了一个XmlInputService,它具有解析各个节点的方法。我只是在控制器中检测它是什么类型的节点,并相应地将其交给服务方法。所以为了保持我的代码干爽和美观,我重新使用我的方法在更高的层次上。如果我将一个类型为Root的文档传递给服务,它将解析根中直接属于它的任何字段,并将子节点(代表我的域类结构中的子节点)传递给适当的解析方法服务。

现在,如果用户上传包含约束违规的xml,即具有非唯一名称的元素等,我显然想要回滚它。假设我调用parseRoot()并向下调用parseChildFoo()。

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

我该怎么做到这一点?

+0

一小时左右后,我发这个帖子,我发现,底层的弹性服务对待嵌套服务电话作为一个事务,所以我还挺回答我自己的问题。对于那些未来会找到答案的人来说,使用failOnError:true作为属性调用save()会抛出一个ValidationException(它是RunTime的子类),因此可以为您结束事务。感谢两位回扣。 – 2011-02-15 12:40:48

回答

1

如果您有一个grails服务具有处理解析的方法,您应该抛出一个异常,该异常从您的服务中扩展java.lang.RuntimeException,以便可以通知用户需要修改其xml 。因此,您的控制器将捕获该异常并向用户提供有意义的错误消息。每当从服务方法抛出runtimeexception时,任何数据库修改的回滚都将由Grails/Spring自动完成。

我对Victor的回答所描述的方法的优点是,您不必编写任何代码就可以让事务在发生故障时回滚。 Grails会为你做。国际海事组织,使用withTransaction闭合内服务方法是没有意义的。

More info here

+0

其实,我在最后一句中说过。如果服务本身不是事务性的,那么`withTransaction`是有意义的。 – 2011-02-15 09:33:43

1

对域对象进行有效性规则验证约束。

当save()违反约束条件时,抛出一个异常并将其捕获到顶级分析级别,然后回滚整个事务。 像:

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

或者你可以简单地让异常飞出服务的方法来控制 - 服务方法是通过默认的事务。