显式关闭数据库连接

Pav*_*vel 1 scala slick play-slick slick-3.0

这是我试图优化的代码:

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
  }

}
Run Code Online (Sandbox Code Playgroud)

我将对数据库进行多次查询,我试图在创建数据库连接的地方删除字符串。是否有任何执行上下文可以用来显式关闭连接?这样代码看起来会更简洁?

是否可以选择在 Future.onComplete 范围内使用数据库连接?

谢谢

Pau*_*ega 5

至于您的评论(在 slick 中显式关闭 db 连接)通常您所做的是在应用程序启动时(或在第一次使用时懒惰地)创建一个连接,然后在应用程序结束时关闭它。

这显然完全取决于您正在运行的应用程序类型:

  • 如果你有DI容器,你可能会在你的DI机制中管理其中的一些(比如Modules in Guice

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

一般方式(无DI)

这样做的最简单的一般方法(假设您没有使用DIplay-slick)可能是这样的:

object DbManager {
  lazy val db = createDb

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

  def close {
      db.close
  }
}
Run Code Online (Sandbox Code Playgroud)

那么你的代码将是:

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 )
  }   
}
Run Code Online (Sandbox Code Playgroud)

上面的代码没有做任何清理 - 当应用程序关闭时(例如 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 )
  }   
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您不会调用:

UserRepo.getAll
Run Code Online (Sandbox Code Playgroud)

但你宁愿需要注入它:

class MyClientCode @Inject() (userRepo: UserRepo) {
  ...
  userRepo.getAll
  ...
}
Run Code Online (Sandbox Code Playgroud)

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

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