I was reading about DatabaseConfig in slick's documentation:
On top of the configuration syntax for
Database, there is another layer in the form ofDatabaseConfigwhich allows you to configure a Slick driver plus a matchingDatabasetogether. 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