I am using Play2.1.1 Java with JPA2.0 with hibernate implementation.
to control the transaction by code instead of using @transactional like below is the normal JPA
something like this:
public static User getUserByIdentity(final AuthUserIdentity identity) {
try {
return JPA.withTransaction(new play.libs.F.Function0<User>() {
public User apply() {
return User.findByAuthUserIdentity(identity);
}
});
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
After some time research, I write a method JPAUtil referring to JPA provided by Play which can use normally to control the transaction manually from the service layer actually everywhere.
public class JPAUtil {
static ThreadLocal<EntityManager> currentEntityManager = new ThreadLocal<EntityManager>();
/**
* Get the EntityManager for specified persistence unit for this thread.
*/
public static EntityManager em(String key) {
Application app = Play.application();
if (app == null) {
throw new RuntimeException("No application running");
}
JPAPlugin jpaPlugin = app.plugin(JPAPlugin.class);
if (jpaPlugin == null) {
throw new RuntimeException("No JPA EntityManagerFactory configured for name [" + key + "]");
}
EntityManager em = jpaPlugin.em(key);
if (em == null) {
throw new RuntimeException("No JPA EntityManagerFactory configured for name [" + key + "]");
}
bindForCurrentThread(em);
return em;
}
/**
* Get the default EntityManager for this thread.
*/
public static EntityManager em() {
EntityManager em = currentEntityManager.get();
if (em == null) {
return em(Constants.DATASOURCEKEY);
}
return em;
}
/**
* Bind an EntityManager to the current thread.
*/
public static void bindForCurrentThread(EntityManager em) {
currentEntityManager.set(em);
}
public static void closeEM() {
EntityManager em = currentEntityManager.get();
if (em != null) {
em.close();
}
bindForCurrentThread(null);
}
public static void beginTransaction() {
em().getTransaction().begin();
}
public static void commitTransaction() {
em().getTransaction().commit();
}
}