通过原子的不同模型进行DB调用

时间:2015-02-01 17:32:09

标签: scala playframework playframework-2.3 anorm

我们假设有两个模型Model1Model2,每个模型都有一组调用DB来检索或写入数据的基本方法。对于一个Model1,可以存在多个Model2,当插入(Model1, List[Model2])时,所有这些数据都来自同一表单。当前的实现执行以下操作:

  1. 使用Model1的插入方法插入Model1实例。
  2. 正确插入Model1后,请继续使用List[Model2]的插入方法插入Model2
  3. 问题是如果在插入Model2之一时出现问题,Model1将保留在数据库中。一个解决方案是捕获anorm抛出的任何异常,并通过执行与之完全相反的操作来撤消之前执行的任何异常。但是有没有可以使用的解决方案?捕获所有已执行的DB调用并在需要时还原它们的东西?

1 个答案:

答案 0 :(得分:1)

您正在寻找的是DB.withTransaction。它与DB.withConnection完全相同,只是autocommit设置为false,因此如果抛出任何异常,整个事务将被回滚。

示例:

case class Model1(id: Long, something: String, children: List[Model2])

case class Model2(id: Long, name: String)

object Model1 {

    def create(model: Model1): Option[Model1] = {
        DB.withTransaction { implicit c =>
            SQL(...).executeInsert().map { id =>
                 model.copy(
                     id = id,
                     children = Model2.create(model.children)
                 )
            }
        }
    }

}

object Model2 {

    def create(models: List[Model2])(implicit c: java.sql.Connection): List[Model2] = {
       ...
    }

}

请注意Model2.create如何接受隐式Connection参数。这样它将使用与Connection事务相同的Model1.create,并允许在失败时回滚。我遗漏了很好的实施细节,因为关键是使用withTransaction,并在同一Connection上运行每个查询。