Я использую Hibernate на своем сервере, (tomcat8, hibernate, postgresql). Каждый конец дня мой код работает (с использованием 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();
}
(вызов хранимой процедуры с использованием встроенного sql через спящий режим).
Когда я запускаю сервер, он сначала выполняет 2 или 3 вызова. Следующие вызовы никогда не заканчиваются. Я воспроизвел проблему локально, вместо каждого дня я назначил расписание для запуска задачи каждые 1 минуту. Он показал мне, как это входит:
Ежедневное обновление Работа Завершена ============== Потребовалось 7338 мс
Ежедневное обновление Работа Заполненные ======= ======= Потребовалось 6473 мс
...
Ежедневное обновление Работа Законченные ============== Это заняло 183381 мс
так что задержка увеличилась, и я решил посмотреть, что происходит внутри е. В приведенном выше коде, когда он пытается выполнить
em.getTransaction().begin();
он никогда не заканчивает и трассировки стека будет показано ниже, как изображение:
В чем причина и как решить проблема?
EDIT 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();
}
}
Что такое 'HibernateUtil' и как работают' closeCurrentEntityManager() 'и' currentEntityManager() '? – Andremoniy
@Andremoniy обновил вопрос. Взгляни, пожалуйста. – maximus
Что такое поле 'entityManager' внутри этого класса? – Andremoniy