如何使DAO线程安全JPA?

时间:2015-07-02 08:47:45

标签: java multithreading jpa

我是JPA和Java的新手。我理解EntityManager和EMF是如何工作的。我有JPAUtill从我获得EntityManager,它使用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();
    }
}

有人可以帮我理解问题以及解决方法吗?

1 个答案:

答案 0 :(得分:0)

从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;
}