【问题标题】:Database transactions in Play framework scala applications (anorm)Play 框架 Scala 应用程序中的数据库事务(异常)
【发布时间】:2014-04-26 22:55:24
【问题描述】:

我正在使用 Play 框架和 scala 开发应用程序。我正在使用 anorm 作为数据访问层。我有一个我无法解决的问题。

简介:我希望能够让数据访问对象 (dao) 中的方法在事务中工作以及被单独调用。

详情:

我的数据访问层由具有仅在数据库上执行特定 SQL 的方法的类组成。传统上它们看起来像:

def list() = DB.withConnection { implicit cn =>
  ...
}

现在我想在事务范围内执行一些方法。像传统的选择更新服务方法一样,但仍然能够单独运行它们。所以,我的想法是这样的:

class Service {
  def fooTransacted() = {
    inTransaction {
      val old = dao.select(id = 2)
      val newObj = old.copy(isActive = true)
      dao.update(newObj)
    }
  }

  def fooSinle() = {
    dao.select(id = 2)
  }
}

我尝试了多种方法,但没有找到任何解决方案。

【问题讨论】:

    标签: scala playframework-2.0 anorm


    【解决方案1】:

    怎么样

    class Dao {
      def foo(id: Long)(implicit connection: Connection) = {
        SQL("select * from foo where id={id}").on('id->id).as(...)
      }
    }
    
    class Service{
      def withConnection = {
        DB.withConnection {implicit connection =>
          Dao.foo(1)
          Dao.foo(2)
        }
      }
    
      def withTransaction = {
        DB.withTransaction {implicit connection =>
          Dao.foo(1)
          Dao.foo(2)
      }
    }
    

    【讨论】:

    • 我考虑过...但这会将异常详细信息放入服务中。理想情况下,不应该与数据层实现无关。抽象的“交易”除外。
    • 迟到的评论.. 但是,如果事务需要在服务中开始和结束,那么您必须在那里维护它。否则,您如何为每个 DAO 提供相同的 Connection
    【解决方案2】:

    我在其他地方(主要是在 Squeryl 中)看到的解决方案大致如下:

    import java.sql.Connection
    object Helper {
      private val conn: ThreadLocal[Connection] = new ThreadLocal
    
      def inTransaction[X](f: Connection => X) = {
        conn.get() match {
          case null =>
            DB.withConnection { newConn =>
              conn.set(newConn)
              try f(newConn)
              finally conn.set(null)
            }
          case c => f(c)
        }
      }
    }
    

    这样,inTransaction 方法是可重入的,所以在dao.select 内部冗余调用它没有坏处。

    如果您愿意,您可以通过公共方法公开 conn,并将 f 的签名更改为 => X - 您会失去一些编译时安全性,但 API 会更简洁一些。

    这种方法的一个缺陷是连接与线程相关联,如果您使用期货或演员,这可能会导致问题,并且进程可以在不同的线程上恢复(无论如何这是一个棘手的领域,但您应该这样做注意)。

    您可能也想研究一下 Squeryl - 它可能已经满足您的需求。

    【讨论】:

      猜你喜欢
      • 2021-02-13
      • 2017-05-06
      • 1970-01-01
      • 2015-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多