簡體   English   中英

如何使DAO線程安全的JPA?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM