blocking-slick
Provides Slick2 compatible blocking API for Slick3.
Setup
Add following dependency to your build.sbt
:
// for Slick 3.3
libraryDependencies += "com.github.takezoe" %% "blocking-slick-33" % "0.0.13"
// for Slick 3.2
libraryDependencies += "com.github.takezoe" %% "blocking-slick-32" % "0.0.11"
// for Slick 3.1
libraryDependencies += "com.github.takezoe" %% "blocking-slick-31" % "0.0.7"
You can enable blocking API by import the blocking driver as follows:
import com.github.takezoe.slick.blocking.BlockingH2Driver.blockingApi._
Slick2 style blocking API
See the example of use of blocking API provided by blocking-slick:
val db = Database.forURL("jdbc:h2:mem:test")
db.withSession { implicit session =>
// Create tables
models.Tables.schema.create
// Insert
Users.insert(UsersRow(1, "takezoe"))
// Insert returning new id
val newID: Long = (Users returning Users.map(_.id)).insert(UsersRow(1, "takezoe"))
// Select
val users: Seq[UserRow] = Users.list
// Select single record
val user: UserRow = Users.filter(_.id === "takezoe".bind).first
// Select single record with Option
val user: Option[UserRow] = Users.filter(_.id === "takezoe".bind).firstOption
// Update
Users.filter(t => t.id === 1.bind).update(UsersRow(1, "naoki"))
// Delete
Users.filter(t => t.id === 1.bind).delete
// Drop tables
models.Tables.schema.remove
}
Plain sql can be executed synchronously as well.
val id = 1
val name = "takezoe"
val insert = sqlu"INSERT INTO USERS (ID, NAME) VALUES (${id1}, ${name1})"
insert.execute
Transaction is available by using withTransaction
instead of withSession
:
// Transaction
db.withTransaction { implicit session =>
...
}
DBIO support
blocking-slick also provides a way to run DBIO
synchronously. It would help to rewrite Slick2 style code to Slick3 style code gradually.
db.withSession { implicit session =>
val id1 = 1
val id2 = 2
val name1 = "takezoe"
val name2 = "chibochibo"
val insert1 = sqlu"INSERT INTO USERS (ID, NAME) VALUES (${id1}, ${name1})" andThen
sqlu"INSERT INTO USERS (ID, NAME) VALUES (${id2}, ${name2})"
insert1.run
val query = for {
count <- sql"SELECT COUNT(*) FROM USERS".as[Int].head
max <- sql"SELECT MAX(ID) FROM USERS".as[Int].head
} yield (count, max)
val (count1, max1) = query.run
assert(count1 == 2)
assert(max1 == 2)
}
Note that using flatMap
and andThen
requires an ExecutionContext
, but if you run that code synchronously that value will be ignored.
Resources
You can see actual codes in the testcase, and also a blocking-slick with Play2 and play-slick example is available at here.