明确关闭光滑的数据库连接
explicitly close db connection in 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
}
}
我将对数据库进行多次查询,我试图在创建数据库连接时删除字符串。有没有我可以用来显式关闭连接的执行上下文?这样代码会看起来更简洁?
是否有在 Future.onComplete 范围内获取已用数据库连接的选项?
谢谢
至于您的评论 (),通常您所做的是在应用程序启动时(或在首次使用时懒惰地)创建连接,然后在应用程序结束时关闭它。
这显然完全取决于你是什么类型的应用程序运行:
如果您有 DI
容器,您可能会在 DI
机制中管理其中的一些(例如 Guice
中的 Module
s)
如果您有网络应用程序,特别是例如Play
- 您可能会使用 play-slick
为您执行此初始化/关闭(有点)。
一般方式(无DI)
最简单的通用方法(假设您没有使用 DI
或 play-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
托管依赖项拉取(如上所示)。
这是我要优化的代码:
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 范围内获取已用数据库连接的选项?
谢谢
至于您的评论 (
这显然完全取决于你是什么类型的应用程序运行:
如果您有
DI
容器,您可能会在DI
机制中管理其中的一些(例如Guice
中的Module
s)如果您有网络应用程序,特别是例如
Play
- 您可能会使用play-slick
为您执行此初始化/关闭(有点)。
一般方式(无DI)
最简单的通用方法(假设您没有使用 DI
或 play-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
托管依赖项拉取(如上所示)。