Blankman
Blankman

Reputation: 266988

Can I wrap sessions to create a transaction with slick?

I have my DAO code that looks like:

UserDao.scala:

def save(user: User)(implicit session: Session) ... {
   ....
}

Then UserService:

def save(user: User) .. {
  db.withSession { implicit session =>
      userDao.save(user)
   }
}

I have other ABCService classes that have the exact same pattern for my other models.

Now my question is, now I want to create a transaction around multiple calls, is this possible?

OtherService:

   userService.save(user)
   accountService.save(account)

Now if either of those calls fail, I want it to rollback. The problem is the sessions are handled indepentaley currently in each Service class, so if the userService.save(user) passes but accountService.save fails, I have data that is in a bad state.

How can I solve this problem?

Upvotes: 1

Views: 1260

Answers (2)

Hanfei Sun
Hanfei Sun

Reputation: 47061

Maybe you could give a look at https://github.com/tim-group/scalaquery_nested

Their implementation looks very concise: https://github.com/tim-group/scalaquery_nested/blob/master/src/main/scala/com/timgroup/scalaquery_nested/NestedScalaQuerySessionsAndTransactions.scala

But they use exception to detect wrapped session, not sure whether it has performance issue for complicated session/transaction nesting..

Upvotes: 0

Michael Zajac
Michael Zajac

Reputation: 55569

Slick has withTransaction that will work exactly the same as withSession, except that everything is executed within a transaction.

Require the signatures of your service functions to have an implicit: Session parameter (if they're to be used within a transaction), and remove the provisioned Session from within them:

def save(user: User)(implicit: Session) {
    userDao.save(user)
}

Then provide that Session via withTransaction:

db.withTransaction{ implicit session =>
     userService.save(user)
     accountService.save(account)
}

Upvotes: 7

Related Questions