Atomic MySQL transactions in Anorm
Asked Answered
B

1

5

I have written a simple hit counter, that updates a MySQL database table using Anorm. I want the transaction to be atomic. I think that the best way would be to join all of the SQL strings together and do one query, but this doesn't seem to be possible with Anorm. Instead I have placed each select, update and commit on separate lines. This works but I can't help thinking that their must be a better way.

private def incrementHitCounter(urlName:String) {
  DB.withConnection { implicit connection =>
    SQL("start transaction;").executeUpdate()
    SQL("select @hits:=hits from content_url_name where url_name={urlName};").on("urlName" -> urlName).apply()
    SQL("update content_url_name set hits = @hits + 1 where url_name={urlName};").on("urlName" -> urlName).executeUpdate()
    SQL("commit;").executeUpdate()
  }
}

Can anyone see a better way to do this?

Bilski answered 16/3, 2014 at 1:18 Comment(0)
A
10

Use withTransaction instead of withConnection like this:

private def incrementHitCounter(urlName:String) {
  DB.withTransaction { implicit connection =>
    SQL("select @hits:=hits from content_url_name where url_name={urlName};").on("urlName" -> urlName).apply()
    SQL("update content_url_name set hits = @hits + 1 where url_name={urlName};").on("urlName" -> urlName).executeUpdate()
  }
}

And why would you even use a transaction here? This should work as well:

private def incrementHitCounter(urlName:String) {
  DB.withConnection { implicit connection =>
    SQL("update content_url_name set hits = (select hits from content_url_name where url_name={urlName}) + 1 where url_name={urlName};").on("urlName" -> urlName).executeUpdate()
  }
}
Accretion answered 17/3, 2014 at 10:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.