简体   繁体   中英

explicitly close db connection in slick

Here is code I am trying to optimise:

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
  }

}

I going to have number of query to the DB I am trying to get rid of string where I am creating DB connection. Is there any execution context I can use to close connection explicitly ?? so code will look more concise ?

Is there option to get used db connection within Future.onComplete scope??

Thanks

As for your comment ( explicitly close db connection in slick ) normally what you do is to create a connection on an application startup (or lazily on first use) and then closing it at the application end.

This obviously all depends what kind of application you are running:

  • if you are having DI container you would probably manage some of this in your DI mechanisms (like Module s in Guice )

  • if you are having web application, specifically eg Play - you would probably use play-slick that does this initialization / shutting down for you (kind of).

General way (no DI)

The easiest general way (assuming you are not using DI or play-slick ) of doing this would be perhaps something like this:

object DbManager {
  lazy val db = createDb

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

  def close {
      db.close
  }
}

Then your code would be:

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 )
  }   
}

Above code doesn't do any cleaning up - this would need to be added to some kind of hook when application is closing (in case eg of web application) or you would need to manually call DbManager.close at some specified time (when you are closing the application).

Play slick

You would probably need to start from here: https://github.com/playframework/play-slick/tree/master/samples/basic (most basic sample showing play-slick configuration).

Updating your answer with this would be:

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 )
  }   
}

In this scenario you wouldn't call:

UserRepo.getAll

but you would rather need to inject it:

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

You would need to obviously configure it in your configuration but this should be very straightforward to do with the sample provided above.

So in short your Play application will have database connection configuration and would do all initialization / cleaning up. Your external modules (like the one you described in your comment) would simply pull DatabaseConfigProvider as Guice managed dependency (as show above).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM