Transactional method in Scala Play with Slick (looks like Spring @Transactional, maybe?)

I know that scala, as a functional language, should work differently than a regular OO language such as Java, but I am sure there should be a way to wrap a group of database changes in one transaction that provides atomicity, as well as any other ACID property.

As explained in slick docs ( http://slick.lightbend.com/doc/3.1.0/dbio.html ), DBIOAction allows you to group db operations in a transaction as follows:

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)

However, my use case (and most real-world examples that I can think of), I have a code structure with a controller that provides code for my REST endpoint, this controller calls several services, and each service delegates database operations for DAO.

An example of my regular code:

class UserController @Inject(userService: UserService) {
  def register(userData: UserData) = {
    userService.save(userData).map(result => Ok(result))
  }
}

class UserService @Inject(userDao: UserDao, addressDao: AddressDao) {
  def save(userData: UserData) = {
    for {
      savedUser <- userDao.save(userData.toUser)
      savedAddress <- addressDao.save(userData.addressData.toAddress)
    } yield savedUser.copy(address = savedAddress)
  }
}

class SlickUserDao {
  def save(user: User) = {
    db.run((UserSchema.users returning UserSchema.users)).insertOrUpdate(user)
  }
}

This is a simple example, but most of them have more complex service level business logic.

I do not want:

  • My DAOs must have business logic and decide which database operations should be performed.
  • Return DBAction from my DAOs and set persistence classes. This completely destroys the purpose of using DAO in the first place and makes further refactoring much more difficult.

, , - , , , .

Slick Scala Play? , , .

, slick? , , - .

EDIT:

, , , , slick . : http://tastefulcode.com/2015/03/19/modern-database-access-scala-slick/.

, , - , , , .

, - . -, .

, , , , , - , . . - .

? git, , ? , , - , ? , , Anorm , , , ( Slick).

+4
1

.. . " " - . DBIO[User] DAO, . , slick.

class UserController @Inject(userService: UserService) {
  def register(userData: UserData) = {
    userService.save(userData).map(result => Ok(result))
  }
}

class UserService @Inject(userDao: UserDao, addressDao: AddressDao) {
  def save(userData: UserData): Future[User] = {
    val action = (for {
      savedUser <- userDao.save(userData.toUser)
      savedAddress <- addressDao.save(userData.addressData.toAddress)
      whatever <- DBIO.successful(nonDbStuff)
    } yield (savedUser, savedAddress)).transactionally

    db.run(action).map(result => result._1.copy(result._2))
  }
}

class SlickUserDao {
  def save(user: User): DBIO[User] = {
    (UserSchema.users returning UserSchema.users).insertOrUpdate(user)
  }
}
  • save .
  • , db.
  • .
  • , / .

, . . Slick 3.0 Transaction.

+3

All Articles