有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Hibernate在事务开始时冻结

使用我的SQL Hibernate,Tom Hibernate。 每天结束时,我的代码都会运行(使用Quartz)一些代码,这些代码在存储过程内部调用(hibernate):

public void execute(JobExecutionContext context)
        throws JobExecutionException {
    log.info("=========Start daily update==========");
    long startTime = System.currentTimeMillis();
    boolean transactionCompleted = false;
    int retryCount = HibernateUtil.RETRY_COUNT;

    HibernateUtil.closeCurrentEntityManager();

    EntityManager em = HibernateUtil.currentEntityManager();

    while (!transactionCompleted)
    {
        try {
            em.getTransaction().begin();
            dailyUpdateDao.dailyUpdate();
            em.getTransaction().commit();
            transactionCompleted = true;
        } catch (PersistenceException ex) {
            if (!HibernateUtil.isDeadlockException(ex) || retryCount == 0) {
                log.error("non deadlock error", ex);
                throw ex;
            }

            log.error("deadlock detected. Retrying {}", HibernateUtil.RETRY_COUNT - retryCount);
            retryCount--;
            if (em.getTransaction().isActive()) {
                em.getTransaction().rollback();
            }
            try {
                Thread.sleep(HibernateUtil.sleepIntervalWhenDeadlockDetected(retryCount));
            } catch(Exception sleepex) {
                log.error("non deadlock sleep ex", ex);
                throw ex;
            }
        }
    }

    log.info("===========Daily Update Job Completed ============== It took {} ms", System.currentTimeMillis() - startTime);
}

上述代码中的dailyUpdate函数执行以下操作:

public void dailyUpdate() {
    String sql = "select count(*) FROM daily_update()";
    EntityManager em = HibernateUtil.currentEntityManager();
    em.createNativeQuery(sql).getSingleResult();
}

(通过hibernate使用本机sql调用存储过程)

当我运行服务器时,它通常会先进行2到3次调用。接下来的通话永远不会结束。我在本地复制了这个问题,而不是每天,我把时间表改为每1分钟开始一次任务。它向我展示了这样的日志:

Daily Update Job Completed ============== It took 7338 ms

Daily Update Job Completed ============== It took 6473 ms

...

Daily Update Job Completed ============== It took 183381 ms

所以延迟增加了,我决定看看里面发生了什么。 在上面的代码中,当它试图执行

em.getTransaction().begin();

它永远不会结束,堆栈跟踪如下图所示:

Stacktrace of frozen execution

原因是什么?如何解决问题

编辑1:currentEntityManager和closeCurrentEntityManager代码:

public class HibernateUtil {
...
private static EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory(PERSISTENT_UNIT);
public static EntityManager currentEntityManager(EntityManagerFactory emf)
        throws HibernateException {
    EntityManager em = (EntityManager) entityManager.get();
    if (em == null||!em.isOpen()) {

        em = emf.createEntityManager();

        entityManager.set(em);
    }
    return em;
}

public static void closeCurrentEntityManager() {
    EntityManager s = (EntityManager) entityManager.get();
    try {
        if (s != null) {
            if (s.getTransaction().isActive()) {
                if (s.getTransaction().getRollbackOnly()) {
                    s.getTransaction().rollback();
                } else {
                    s.getTransaction().commit();
                }
            }
            s.close();
        }
    } finally {
        entityManager.remove();
    }
}

共 (1) 个答案

  1. # 1 楼答案

    好的,很好,在发布了关于什么是HibernateUtilcloseCurrentEntityManager()currentEntityManager()如何工作,以及这个类中的entityManager领域的详细信息之后,一切都变得清晰了

    看看你的代码。首先关闭“当前”实体管理器:

    HibernateUtil.closeCurrentEntityManager();

    但是你应该考虑到这样一个事实:quartz scheduller在不同的线程中开始它的任务。所以

    public static void closeCurrentEntityManager() {
        EntityManager s = (EntityManager) entityManager.get();
    

    将返回null(如果是新线程)

    下一步调用

     EntityManager em = HibernateUtil.currentEntityManager();
    

    这也将创建新的EntityManager,因为它是新线程:

    em = emf.createEntityManager();
    

    现在看看你的屏幕截图:你的beginTransaction()方法正在等待新的连接。这里发生的事情是,您创建了新的entitmanager,它打开了新的连接,但没有关闭它。所以基本上你的池中没有免费的连接

    只需尝试将HibernateUtil.closeCurrentEntityManager();移动到final { ... }块中,然后再次测试