Bomgar
Bomgar

Reputation: 625

Slick 3 Transactions

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

Answers (2)

panther
panther

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

Gregor Ra&#253;man
Gregor Ra&#253;man

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

Related Questions