[英]How to make DAO thread safe JPA?
我是JPA和Java的新手。 我了解EntityManager和EMF是如何工作的。 我從那里獲取EntityManager的JPAUtill,它使用ThreadLocal變量,這使EntityManager線程安全。 我有DAO,當我同時具有1萬個線程訪問時,我會在其中堅持新用戶。
我看到以下異常:
javax.persistence.PersistenceException: org.hibernate.SessionException: Session is closed!
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:614)
這是我的DAO代碼
try{
entityManager = JPAUtil.getEntityManager();
user.setArea(getArea());
user.setCity(getCity());
user.setPassword("xxxxx");
user.setEmail_Id(getEmail_Id());
user.setMobile_Num(TempMobile_Num);
user.setFirst_Name(getFirst_Name());
user.setSession_Id("0");
user.setEmail_Verification_Status("NOT VERIFIED");
user.setBalance(new BigDecimal(0.00));
if (!entityManager.getTransaction().isActive()){
entityManager.getTransaction().begin();
}
entityManager.persist(user);
JPAUtil.commit();
} catch (Exception e) {
logger.info(e);
e.printStackTrace();
} finally{
if(entityManager.isOpen())
JPAUtil.closeEntityManager();
}
JPAUtil:
public class JPAUtil {
private static Logger logger = Logger.getLogger(JPAUtil.class);
private static EntityManager entityManager = null;
private static final ThreadLocal<EntityManager> threadLocal;
private static EntityManagerFactory emf = null;
static {
try {
emf = Persistence.createEntityManagerFactory("XYZDB");
threadLocal = new ThreadLocal<EntityManager>();
} catch (Throwable ex) {
logger.info("JPAUtil Exception", ex);
throw new ExceptionInInitializerError(ex);
}
}
public static EntityManager getEntityManager() {
try {
entityManager = threadLocal.get();
if (entityManager == null || !entityManager.isOpen()) {
JPAUtil.entityManager = emf.createEntityManager();
threadLocal.set(entityManager);
} else if (!emf.isOpen()) {
entityManager = threadLocal.get();
emf = Persistence.createEntityManagerFactory("XYZDB");
JPAUtil.entityManager = emf.createEntityManager();
threadLocal.set(entityManager);
}
} catch (Throwable ex) {
logger.info("JPAUtil Exception", ex);
throw new ExceptionInInitializerError(ex);
}
return JPAUtil.entityManager;
}
public static void closeEntityManager() {
EntityManager entityManager = threadLocal.get();
if (entityManager != null) {
entityManager.close();
threadLocal.set(null);
}
}
public static void closeEntityManagerFactory() {
emf.close();
}
public static void commit() {
if (!entityManager.getTransaction().isActive()) {
entityManager.getTransaction().begin();
}
entityManager.getTransaction().commit();
}
public static void rollback() {
if (!entityManager.getTransaction().isActive()) {
entityManager.getTransaction().begin();
}
entityManager.getTransaction().rollback();
}
}
有人可以幫我理解這個問題以及如何解決嗎?
從JPAUtil中刪除此static
變量:
private static EntityManager entityManager = null;
您仍在使用static
變量; 您並沒有真正使用ThreadLocal
。
將您的getEntityManager
更改為此:
public static EntityManager getEntityManager() {
EntityManager entityManager;
try {
entityManager = threadLocal.get();
if (entityManager == null || !entityManager.isOpen()) {
entityManager = emf.createEntityManager();
threadLocal.set(entityManager);
}
} catch (Throwable ex) {
logger.info("JPAUtil Exception", ex);
throw new ExceptionInInitializerError(ex);
}
return entityManager;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.