【问题标题】:Grails transactions (not GORM based but using Groovy Sql)Grails 事务(不是基于 GORM,而是使用 Groovy Sql)
【发布时间】:2013-01-28 20:23:15
【问题描述】:

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

所以,我使用Groovy Sql Class 来完成这项工作。数据库调用在我的控制器中调用的服务中完成。

此外,我的数据源是通过 Tomcat 中的 DBCP 声明的 - 所以它没有在 Datasource.groovy 中声明。

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

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

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

如果这个 SQL 对象是从 DataSource 创建的,那么这个方法什么也不做。

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

【问题讨论】:

    标签: sql grails groovy transactions


    【解决方案1】:

    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
    

    使用缓存连接在事务中执行关闭。如果闭包只接受一个参数,它将与连接一起调用,否则将不带参数调用。

    试一试。

    【讨论】:

      【解决方案2】:

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

      • 我将我的服务声明为事务性服务

        静态事务 = true

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

        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
      }
      

      【讨论】:

      • 服务默认是事务性的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-21
      相关资源
      最近更新 更多