TransactionRequiredException при обновлении - PullRequest
0 голосов
/ 18 июня 2019

Я получаю исключение в логах:

javax.persistence.TransactionRequiredException: выполнение запроса на обновление / удаление

Это ветка isNew = false в методе updateSomething(). Я не заметил исключений из другой ветки.

Я нашел кое-что в stackoverflow об использовании entityManager.joinTransaction();, но когда я это сделал, я получил еще одно исключение:

java.lang.IllegalStateException: не разрешено присоединяться к транзакции в общем EntityManager

Я хотел бы обработать это правильно, чтобы метод updateSomething работал. Я также хотел бы знать, является ли хорошей идеей наличие вложенной аннотации @Transactional и каков эффект вызова транзакционного метода из транзакционного метода - я считаю, что внутренняя транзакция выполняется в своей собственной транзакции и фиксирует в базе данных.

Примечание: HACK не работает, я оставил его в качестве примера того, что я пробовал.

Идея: Поможет ли делать entityManager.flush() после каждого обновления (обновление с использованием собственного SQL)?

@Transactional
public boolean generateLogsComposite() {
    Connection conn = getConnection();
    writeSomeData(conn);//write some data using a separate connection
    boolean isNew = checkSomeData();//The check works with the data from writeSomeData although not using he connection conn
    if(isNew) {
        generateEmail(conn);//Calls a stored procedure on connection conn.
        updateRunEnvOnEmail(emailId, runEnv);
        //Now the data from generateEmail and updateRunEnvOnEmail is present
    } else {
        updateSomething();//has a javax.persistence.TransactionRequiredException: Executing an update/delete query
    }
}

private void joinTransaction() {
    try {
        //HACK vs javax.persistence.TransactionRequiredException: Executing an update/delete query
        entityManager.joinTransaction();
        logger.debug("Joined transaction successfully");
    } catch(Throwable t) {
        //java.lang.IllegalStateException: Not allowed to join transaction on shared EntityManager
    }
}

@Transactional
public void updateRunEnvOnEmail(Long emailId, String runEnv)
{
    try
    {
        //HACK vs javax.persistence.TransactionRequiredException: Executing an update/delete query
        joinTransaction();

        Query query = entityManager
                .createNativeQuery("update XXX.EMAIL e set e.RUN_ENVIRONMENT = :runEnv where e.EMAIL_ID = :emailId");
        query.setParameter("runEnv", runEnv);
        query.setParameter("emailId", emailId);
        query.executeUpdate();
    } catch (Exception e)
    {
        logger.debug("Error while updating RUN_ENVIRONMENT on Email : "
                + emailId + " ::: " + e);
    }

}

@Transactional
public void updateSomething()
{
    try
    {
        //HACK vs javax.persistence.TransactionRequiredException: Executing an update/delete query
        joinTransaction();

        Query query = entityManager
                .createNativeQuery("update something");
        query.executeUpdate();
    } catch (Exception e)
    {
        logger.debug("Error while updating something",e);
    }

}

1 Ответ

1 голос
/ 18 июня 2019

Как правило, JPA не любит, чтобы обновления вызывались вне транзакций, если это явно не настроено для этого.Правильный способ сделать это будет следующим:

entityManager.getTransaction().begin();
// do your updates
entityManager.getTransaction().commit();

Однако, если вы хотите, чтобы транзакции, управляемые Spring (ваш IllegalStateException предлагает так), вы можете захотеть посмотреть на @Transactional(но убедитесь, что вы указали правильный менеджер транзакций, возможно, вы захотите посмотреть ответы на TransactionRequiredException Выполнение запроса на обновление / удаление для получения дополнительной информации).

...