Reputation: 625
I'm confused by the way the slick 3 documentation describes transactions. I have slick 2 code that looks like this:
def doSomething(???) = DB.withTransaction { implicit session =>
userDao.doSomething(???)
addressDao.doSomething(???)
contactDao.doSomething(???)
}
How can i span a transaction in slick 3?
Upvotes: 15
Views: 13483
Reputation: 767
val dbAction = (
for {
user <- userTable.doSomething
address <- addressTable.doSomething
contact <- contactTable.doSomething
} yield()
).transactionally
val resultFuture = db run dbAction
You just need to wrap your action into 'transactionally'. Slick would take care of running all wrapped DB actions as a transaction.
Apart from the standard advantages of having a more reactive/functional/async way of writing code, it allows couple of performance improvements. Like it can determine at runtime if multiple actions can use the same session or not. In Slick 2.0, whenever you use 'withTransaction' or 'withSession' that opens a new jdbc session while here it has potential to reuse the same.
Upvotes: 15
Reputation: 3081
Please have a look at the documentation here http://slick.typesafe.com/doc/3.0.0/dbio.html#transactions-and-pinned-sessions
The idea is that you wrap a sequence of IO operations into a transactionally
like shown in this example:
val a = (for {
ns <- coffees.filter(_.name.startsWith("ESPRESSO")).map(_.name).result
_ <- DBIO.seq(ns.map(n => coffees.filter(_.name === n).delete): _*)
} yield ()).transactionally
val f: Future[Unit] = db.run(a)
This way Slick still process all the operations reactively, but it runs them all in one transaction sequentially.
So your example would look like this:
def doSomething(???) = (for {
_ <- userDao.doSomething(???)
_ <- addressDao.doSomething(???)
_ <- contactDao.doSomething(???)
} yield()).transactionally
Upvotes: 17