I recently worked with
Hibernate JPA 2.0 in multithreading application, and have to deal and
manage somme thread safe issues. So I'd like to share this post with who 'll face the same problems in his next
devoloppements.
In my case, i try to develop a multi-threading standalone application in which every
worker thread can make database transactions (insert or update). These
transactions must not delay the thread in any case.
First of all, keep in mind that JPA
EntityManager are not synchronized. That means that you cannot create
an instance of EntityManager and do all the transactions from that
instance. Although, JPA EntityManagerFactory is a synchronized object
and hence you can create as many EntityManager you want from an instance
of EntityManagerFactory.
My designed possible solution
is an EntityManagerHelper
class:public class EntityManagerHelper {
private static final EntityManagerFactory emf;
private static final ThreadLocal<EntityManager> threadLocal;
static {
emf = Persistence.createEntityManagerFactory("MyPersistanceUnit");
threadLocal = new ThreadLocal<EntityManager>();
}
public static EntityManager getEntityManager() {
EntityManager em = threadLocal.get();
if (em == null) {
em = emf.createEntityManager();
// set your flush mode here
threadLocal.set(em);
}
return em;
}
public static void closeEntityManager() {
EntityManager em = threadLocal.get();
if (em != null) {
em.close();
threadLocal.set(null);
}
}
public static void closeEntityManagerFactory() {
emf.close();
}
public static void beginTransaction() {
getEntityManager().getTransaction().begin();
}
public static void rollback() {
getEntityManager().getTransaction().rollback();
}
public static void commit() {
getEntityManager().getTransaction().commit();
}
}
This allows me to use the JPA trade safe object EntityManagerFactory to provide the same
JPA EntityManager instance call.
JPA EntityManager instance call.
Next is to call this
EntityManagerHelper in seperate class
public class DatabaseService { public static void insertEntity(AnEntity entity){ EntityManager em =
EntityManagerHelper
.
getEntityManager
(); try{
(); em.merge(entity);
beginTransaction
EntityManagerHelper.
.commit(); }catch(Exception e){ logger.fatal("Entity Insert Exception:",e);
EntityManagerHelper
.rollback(); } finally{
EntityManagerHelper
EntityManagerHelper.
closeEntityManager
(); } } public static AnEntity findEntitybyId(int id){
EntityManager em =
EntityManagerHelper
.AnEntity anEntity = em.find(AnEntity.class, id);
getEntityManager
();
EntityManagerHelper.
return anEntity; } }
closeEntityManager
();
I hope this'll help.
Aucun commentaire:
Enregistrer un commentaire