在光滑中显式关闭数据库连接

时间:2017-02-19 14:47:56

标签: scala slick slick-3.0 play-slick

以下是我要优化的代码:

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
  }

}

我将对DB有多少查询我试图摆脱我创建数据库连接的字符串。是否有任何执行上下文可用于显式关闭连接?所以代码看起来会更简洁?

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

由于

1 个答案:

答案 0 :(得分:4)

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

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

  • 如果您拥有DI容器,则可能会在DI机制中管理部分内容(例如Module中的Guice

  • 如果您正在使用网络应用程序,特别是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托管依赖项(如上所示)。