sql - 每个请求播放 2 个事务

标签 sql scala transactions anorm playframework-2.3

对我来说最方便的事务管理是对整个 http 请求使用一个可选事务。这意味着第一个 SQL 语句应该从池中检索连接,启动事务,在请求处理完成后,应该提交事务(如果抛出异常,则回滚)并关闭连接。当然,如果需要,更细粒度的事务管理必须是可能的。

Play 2 是否支持开箱即用?我可能可以自己实现它,但我正在寻找现成的解决方案。

我查看了 DB 对象,但似乎 DB.withConnection 每次都使用新的连接(和事务)。

如果重要的话,我正在使用 Scala 和 Anorm db 库。

最佳答案

DB.withTransaction是你想要的。就像 DB.withConnection ,它将从连接池中为所有包含的 SQL 函数提供一个连接。由于您希望每个请求使用一个事务,因此在 Controller 函数中调用它似乎是最有意义的,并且要求所有模型函数都具有隐式连接参数。

模型:

object Product {

    def checkInventory(id: Long)(implicit c: Connection): Int = SQL(...)

    def decrementInventory(id: Long, quantity: Int)(implicit c: Connection): Boolean = SQL(...)

}

object Cart {

    def addItem(id: Long, quantity: Int)(implicit c: Connection): Boolean = SQL(...)

}

Controller 功能:
def addToCart(id: Long, quantity: Int) = Action {

    DB.withTransaction{ implicit connection =>
       if(Product.checkInventory(id) >= quantity && Product.decrementInventory(id, quantity)) {

        Cart.addItem(id, quantity)
        ....
       } else {
           BadRequest
       }
    }
}

免责声明:这显然不是逻辑上合理的购物车交易,而只是使用数据库交易的简单说明。

关注 Action documentation 中的组合示例,你可以做个特别的Transaction自动为每个请求提供事务的操作:
object Transaction extends ActionBuilder[Request] {
    def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
        DB.withTransaction{implicit connection => block(request)}
    }
}

并像 Action 一样使用它:
def addToCart(id: Long, quantity: Int) = Transaction {
    Product.checkInventory(id)

    ...
}

陷阱 :以这种方式为每个请求提供一个事务很方便,尤其是当您的大多数 Controller 功能都应该表示原子操作时。但是,此方法不会释放Connection从交易到Result已退还给用户。这意味着,如果您要返回一个需要很长时间为客户端提供/呈现的大型数据集,那么您将保持连接的时间比您真正需要的时间长得多。

关于sql - 每个请求播放 2 个事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24096536/

相关文章:

Mysql 选择匹配 4、5 或 6 列

javascript - 使用具有多个搜索条件的 Knex.js 和 SQL 的条件过滤器

mysql - 如何在 MySQL 的 IF 内设置多个用户变量

scala - 如何为每个子类创建一份数据副本?

java - java中的开放类或隐式类

python - Pony ORM 报告记录 "was updated outside of current transaction"而没有其他事务

java - 我可以使用 Selenium 打开应用程序吗?

Scala lambda 样式 (x) => {...} 与 { (x) => ... }

java - 在Java中将大约80000条大数据插入postgres数据库失败

c# - 使用 MySqlTransaction 回滚