【问题标题】:explicitly close db connection in slick在 slick 中明确关闭数据库连接
【发布时间】:2017-07-08 19:00:51
【问题描述】:

这是我要优化的代码:

object UserRepo
{
  val users = TableQuery[Users]

  val dbName = "db"

  lazy val queryAllUsers = for (user <- users) yield user

  type UserRow =  (Int, String, String, String)

  def getAll() : Future[ Seq[UserRow] ] =
  {
    val db = Database.forConfig( dbName )

    val f: Future[Seq[UserRow]] = db.run( queryAllUsers.result )

    f.onComplete {
      case Success(_) => { db.close() }
      case Failure(_) => { db.close() }
    }

    f
  }

}

我将对数据库进行多次查询,我试图摆脱创建数据库连接的字符串。有没有我可以用来明确关闭连接的执行上下文?所以代码看起来会更简洁?

是否有在 Future.onComplete 范围内使用数据库连接的选项?

谢谢

【问题讨论】:

  • 那么你的意思是你想为这个单一的操作创建(然后关闭)数据库连接?您不应该在应用程序的某种启动/关闭时打开/关闭连接并在执行查询时重新使用连接吗?
  • 好点,您的意思是在应用程序级别管理数据库连接?是的,这可能很好,但据我所知,我将不得不手动创建此代码?浮油中有什么东西吗?
  • 你在用Play吗?
  • 我创建了单独的项目来管理与数据库/数据相关的所有工作,并计划在 Play 项目中以及在数据处理服务中重用它
  • 如果您正在使用 play,查看 play-slick 并简单地使用 DI 可能会很有用。让我用Play 样式DI 更新答案。

标签: scala slick slick-3.0 play-slick


【解决方案1】:

至于您的评论 (explicitly close db connection in slick),通常您所做的是在应用程序启动时(或在第一次使用时懒惰地)创建连接,然后在应用程序端关闭它。

这显然完全取决于您运行的是哪种应用程序:

  • 如果您拥有DI 容器,您可能会在您的DI 机制中管理其中的一些内容(例如Guice 中的Modules)

  • 如果您有 Web 应用程序,特别是例如Play - 您可能会使用 play-slick 为您进行初始化/关闭(有点)。

一般方式(无 DI)

执行此操作的最简单的通用方法(假设您没有使用DIplay-slick)可能是这样的:

object DbManager {
  lazy val db = createDb

  private def createDb = {
      Database.forConfig("db")
  }

  def close {
      db.close
  }
}

那么您的代码将是:

object UserRepo
{
  val users = TableQuery[Users]

  lazy val queryAllUsers = for (user <- users) yield user

  type UserRow =  (Int, String, String, String)

  def getAll() : Future[ Seq[UserRow] ] =
  {
    DbManager.db.run( queryAllUsers.result )
  }   
}

上面的代码没有做任何清理——这需要在应用程序关闭时添加到某种钩子中(例如在 Web 应用程序的情况下),或者您需要在某个指定时间手动调用 DbManager.close (当您关闭应用程序时)。

玩得很流畅

您可能需要从这里开始:https://github.com/playframework/play-slick/tree/master/samples/basic(显示play-slick 配置的最基本示例)。

用这个更新你的答案是:

class UserRepo @Inject() (dbConfigProvider: DatabaseConfigProvider) extends HasDatabaseConfigProvider[JdbcProfile])
{
  import driver.api._

  val users = TableQuery[Users]

  lazy val queryAllUsers = for (user <- users) yield user

  type UserRow =  (Int, String, String, String)

  def getAll() : Future[ Seq[UserRow] ] =
  {
    db.run( queryAllUsers.result )
  }   
}

在这种情况下你不会打电话:

UserRepo.getAll

但你宁愿需要注入它:

class MyClientCode @Inject() (userRepo: UserRepo) {
  ...
  userRepo.getAll
  ...
}

您显然需要在配置中对其进行配置,但这对于上面提供的示例应该非常简单。

简而言之,您的Play 应用程序将具有数据库连接配置,并会进行所有初始化/清理。您的外部模块(如您在评论中描述的模块)只需将 DatabaseConfigProvider 拉为 Guice 托管依赖项(如上所示)。

【讨论】:

  • 好吧,考虑到 scala 代码的简洁程度,我正在考虑在我的项目中使用 play-slick:(播放项目 + Akk 处理服务)。所以,我将有单独的数据模型/表映射等项目。谢谢,
猜你喜欢
  • 2023-03-09
  • 1970-01-01
  • 2013-02-18
  • 2012-07-12
  • 2011-01-14
  • 1970-01-01
  • 2011-10-19
  • 2013-10-16
相关资源
最近更新 更多