Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Atomic MySQL transactions in Anorm

Tags:

mysql

scala

anorm

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?

like image 257
Arthur Avatar asked Mar 16 '14 01:03

Arthur


1 Answers

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()
  }
}
like image 179
serejja Avatar answered Sep 22 '22 13:09

serejja