Skip to content

Instantly share code, notes, and snippets.

@leon
Created January 9, 2014 14:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save leon/8334888 to your computer and use it in GitHub Desktop.
Save leon/8334888 to your computer and use it in GitHub Desktop.
Scala JPA
package actions
import play.api.mvc._
import scala.concurrent.{ExecutionContext, Future}
import javax.persistence._
import play.db.jpa.JPAPlugin
import play.api.Play
import play.api.mvc.SimpleResult
class EntityManagerRequest[A](val em: EntityManager, request: Request[A]) extends WrappedRequest[A](request)
trait JPA {
def entityManager(name: String = "default") = {
val plugin: JPAPlugin = Play.current.plugin(classOf[JPAPlugin]).getOrElse(sys.error("The JPA Plugin is not available"))
plugin.em(name)
}
def jpaAction[A](name: String = "default", readOnly: Boolean = false)(request: Request[A], block: (EntityManagerRequest[A]) => Future[SimpleResult])(implicit ec: ExecutionContext) = {
var em: EntityManager = null
var tx: EntityTransaction = null
try {
em = entityManager(name)
if (!readOnly) {
tx = em.getTransaction
tx.begin()
}
val result = block(new EntityManagerRequest[A](em, request))
val committedResult = result.map { r =>
try {
if(tx != null) {
if (tx.getRollbackOnly) {
tx.rollback()
} else {
tx.commit()
}
}
} finally {
em.close()
}
r
}
committedResult.onFailure {
case ex => {
if (tx != null) {
try {
if (tx.isActive) tx.rollback()
}
catch {
case e: Throwable =>
}
}
em.close()
}
}
committedResult
}
catch {
case t: Throwable => {
if (tx != null) {
try {
tx.rollback()
}
catch {
case e: Throwable =>
}
}
if (em != null) {
em.close()
}
throw t
}
}
}
}
object JPATransaction extends ActionBuilder[EntityManagerRequest] with JPA {
def invokeBlock[A](request: Request[A], block: (EntityManagerRequest[A]) => Future[SimpleResult]) = {
jpaAction()(request, { r: EntityManagerRequest[A] =>
block(r)
})(executionContext)
}
}
object JPAReadOnlyTransaction extends ActionBuilder[EntityManagerRequest] with JPA {
def invokeBlock[A](request: Request[A], block: (EntityManagerRequest[A]) => Future[SimpleResult]) = {
jpaAction(readOnly = true)(request, { r: EntityManagerRequest[A] =>
block(r)
})(executionContext)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment