Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Transactions in Play Framework

I'm using play with DB and anorm and I have quite common methods like these:

def insert(user: User) = {
 DB.withConnection { implicit connection =>
  SQL"""
      insert into user(email, password) values (
       ${user.email}, ${user.password}
      )
    """
    .executeInsert()
  }
}

and

def insert(notification: Notification) = {
   DB.withConnection { implicit connection =>
    SQL"""
      insert into notification(date, text) values (
       ${notification.date}, ${notification.text}
      )
    """
    .executeInsert()
  }
}

So, I have 2 methods which use autocommits whitin their connections. What I want to do is to write something like this, i.e. create user, create notification and have a chance to rollback the all stuff in the case of errors:

def createUserAndSendNotification(user:User) = {
 DB.withTransaction {
   insert(user)
   insert(new Notification)
  }
}

, but methods insert(user) and insert(notification) already have set autocommit = 1, so if the notification inserting will fail, user will be still persisted.

I could write plain SQL in createUserAndSendNotification(user:User), but I would use existing methods like insert(user) and insert(notification). Is it possible?

PS1

Possible solution - make the auxiliary method for the each method used in transaction blocks:

def insert(notification: Notification) = {
 DB.withConnection { implicit connection =>
   insertSql(notification)
  }
}

def insertSql(notification: Notification)(implicit connection: Connection) = {
 SQL"""
      insert into notification(date, text) values (
       ${notification.date}, ${notification.text}
      )
    """.executeInsert[Option[Long]]()
}

So:

def createUserAndSendNotification(user:User) = {
 DB.withTransaction {implicit connection =>
   insertSql(user)
   insertSql(new Notification)
  }
}
like image 312
arctica Avatar asked Dec 03 '25 09:12

arctica


1 Answers

Try supplying the Connection as an implicit arguments to your fine-grained functions, and only acquiring the Connection once in DB.withTransaction:

def insert(user: User)(implicit connection: Connection) = {
  SQL"""
      insert into user(email, password) values (
       ${user.email}, ${user.password}
      )
    """
    .executeInsert()
}

def insert(notification: Notification)(implicit connection: Connection) = {
    SQL"""
      insert into notification(date, text) values (
       ${notification.date}, ${notification.text}
      )
    """
    .executeInsert()
}

def createUserAndSendNotification(user:User) = {
 DB.withTransaction { implicit connection =>
   insert(user)
   insert(new Notification)
  }
}
like image 132
Steve Waldman Avatar answered Dec 05 '25 15:12

Steve Waldman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!