I was reading about DatabaseConfig
in slick's documentation:
On top of the configuration syntax for
Database
, there is another layer in the form ofDatabaseConfig
which allows you to configure a Slick driver plus a matchingDatabase
together. This makes it easy to abstract over different kinds of database systems by simply changing a configuration file.
I don't get this part, how DatabaseConfig
makes the underlying database system more abstract than the Database
approach? Suppose, i'm using DatabaseConfig
in the following test:
import org.scalatest.{Matchers, FlatSpec}
import slick.backend.DatabaseConfig
import slick.driver.JdbcProfile
import slick.driver.PostgresDriver.api._
import scala.concurrent.ExecutionContext.Implicits.global
class DatabaseConfigTest extends FlatSpec with Matchers {
def withDb(test: DatabaseConfig[JdbcProfile] => Any) = {
val dbConfig = DatabaseConfig.forConfig[JdbcProfile]("abstract")
try test(dbConfig)
finally dbConfig.db.close()
}
"DatabaseConfig" should "work" in withDb { dbConfig =>
import Supplier._
val cities = suppliers.map(_.city)
dbConfig.db.run(cities.result).map(_.foreach(println))
}
}
As you can see, if i change my underlying database system from PostgreSQL
to MySQL
, in addition to configuration change, i need to change the import
statement that imports the postgre API to mysql's. On the other hand, If i was using Database
:
import org.scalatest.{FlatSpec, Matchers}
import slick.driver.PostgresDriver.api._
import slick.jdbc.JdbcBackend.Database
import scala.concurrent.ExecutionContext.Implicits.global
class DatabaseTest extends FlatSpec with Matchers {
def withDb(test: Database => Any) = {
val db = Database.forConfig("default")
try test(db)
finally db.close()
}
"Supplier names" should "be fetched" in withDb { db =>
import Supplier._
val names = suppliers.map(_.name)
db.run(names.result).map(_.foreach(println))
}
}
When i'm using Database
, same change on the underlying database, would result in two changes: one in configuration file and the other in source code. With all these being said, how one approach is more abstract than the other one? Am i using DatabaseConfig
wrong?
You are close, but you aren't quite using DatabaseConfig
properly. Rather than importing a specific driver, you need to import the driver associated with the config. Something like this should work:
import org.scalatest.{Matchers, FlatSpec}
import slick.backend.DatabaseConfig
import slick.jdbc.JdbcProfile
//import slick.driver.PostgresDriver.api._
import scala.concurrent.ExecutionContext.Implicits.global
class DatabaseConfigTest extends FlatSpec with Matchers {
def withDb(test: DatabaseConfig[JdbcProfile] => Any) = {
val dbConfig = DatabaseConfig.forConfig[JdbcProfile]("abstract")
/* The api for the driver specified in the config is imported here. */
import dbConfig.driver.api._
try test(dbConfig)
finally dbConfig.db.close()
}
"DatabaseConfig" should "work" in withDb { dbConfig =>
import Supplier._
val cities = suppliers.map(_.city)
dbConfig.db.run(cities.result).map(_.foreach(println))
}
}
This should allow you to switch databases in the config without having to change any code or recompile.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With