【问题标题】:How to enforce creating new transaction in Lift Mapper?如何强制在 Lift Mapper 中创建新事务?
【发布时间】:2013-05-15 12:15:31
【问题描述】:

我们在项目中使用 Lift + Mapper(2.4 版)。我们也在使用每请求事务模式S.addAround(DB.buildLoanWrapper())

在我们的一个请求中,我们需要嵌套事务,我们发现这是有问题的。我们发现可能的“黑客”之一是在单独的线程中启动事务(如下例所示),因为DB 对象使用ThreadLocal 来管理当前连接和事务状态信息。

有没有比下面的更好(更安全且无需多线程)的实现?

  import net.liftweb.db.{DefaultConnectionIdentifier, DB}
  import akka.dispatch.Future

  /**
   * Will create a new transaction if none is in progress and commit it upon completion or rollback on exceptions.
   * If a transaction already exists, it has no effect, the block will execute in the context
   * of the existing transaction. The commit/rollback is handled in this case by the parent transaction block.
   */
  def inTransaction[T](f: ⇒ T): T = DB.use(DefaultConnectionIdentifier)(conn ⇒ f)

  /**
   * Causes a new transaction to begin and commit after the block’s execution,
   * or rollback if an exception occurs. Invoking a transaction always cause a new one to be created,
   * even if called in the context of an existing transaction.
   */
  def transaction[T](f: ⇒ T): T = Future(DB.use(DefaultConnectionIdentifier)(conn ⇒ f)).get

【问题讨论】:

  • 使用Future(...).get 完全没有意义,因为它使用两个线程而不是一个;请删除它和 Akka 标记,因为这个问题与 Akka 无关。
  • “更好”的实现是什么意思?如果你使用纯 squeryl,你可以自己决定。如果您只使用 Mapper、AFAIK,您也可以自己选择事务范围。
  • 致 Roland Kuhn:Future 在这里精确地用于创建一个单独的执行线程 描述应该改进,因为它缺乏必要的解释,即:如果你有 DB.use 通过使用贷款包装器围绕你的请求,那么这是一种(我还不知道另一种)如何强制进行新交易的方法。由于使用 Thread Locals 简单的嵌套 DB.use 完全没有任何作用

标签: scala transactions lift lift-mapper


【解决方案1】:

不幸的是,似乎没有现有的 API。您可以询问有关在 google 组中添加一个。但是,没有什么可以阻止您执行以下操作:

DB.use(DefaultConnectionIdentidier){ sc =>
  val conn: java.sql.Connection = sc.connection
  // use regular JDBC mechanism here
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-06
    • 1970-01-01
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    • 2022-12-29
    • 2011-06-21
    相关资源
    最近更新 更多