Grails事务(不是基于GORM,而是使用GroovySql)



我的Grails应用程序不使用GORM,而是使用我自己的SQL和DML代码来读取和写入数据库(该数据库是一个巨大的标准化遗留数据库,这是唯一可行的选项)。

因此,我使用GroovySql类来完成这项工作。数据库调用是在我的控制器中调用的服务中完成的。

此外,我的数据源是通过Tomcat中的DBCP声明的,因此它不会在datasource.groovy.中声明

我的问题是,我需要编写一些事务代码,这意味着在一系列成功的DML调用后打开事务并提交,或者在出现错误时回滚整个事务。

我认为分别使用groovy.sql.sql#commit()和groovy.sql.sql#rollback()就足够了。

但在这些方法Javadocs中,GroovySql文档清楚地说明了

如果此SQL对象是从DataSource创建的,则此方法不执行任何操作。

所以,我想知道:在我的上下文中,执行事务的建议方法是什么?即使在数据源声明中禁用自动提交似乎也无关紧要,因为这两个方法"…什么都不做"

Groovy Sql类具有withTransaction

http://docs.groovy-lang.org/latest/html/api/groovy/sql/Sql.html#withTransaction(groovy.lang.Closure)

public void withTransaction(Closure closure)
                     throws java.sql.SQLException

使用缓存连接在事务中执行闭包。如果闭包只有一个参数,那么它将使用连接进行调用,否则它将不使用任何参数进行调用。

试试看。

谢谢James。我还找到了以下解决方案,阅读http://grails.org/doc/latest/guide/services.html:

  • 我宣布我的服务为事务

    静态事务=true

这样,如果发生错误,以前执行的DML将被回滚。
  • 对于每个DML语句,我都抛出一个描述消息的Error。例如:

    try{
        sql.executeInsert("""
           insert into mytable1 (col1, col2) values (${val1}, ${val2})
        """)
    catch(e){
        throw new Error("you cant enter empty val1 or val2")
    }
    try{
        sql.executeInsert("""
           insert into mytable2 (col1, col2) values (${val1}, ${val2})
        """)
    catch(e){
        throw new Error("you cant enter empty val1 or val2. The previous insert is rolledback!")
    }
    

终于明白了!从控制器调用服务时,必须处于try-catch中,如下所示:

try{
    myService.myMethod(params)
}catch(e){
    //http://jts-blog.com/?p=9491
    Throwable t = e instanceof UndeclaredThrowableException ? e.undeclaredThrowable : e
    // use t.toString() to send info to user (use in view)
    // redirect / forward / render etc
}

最新更新