2013-04-01 6 views
4

Я получаю эту ошибку, когда пытаюсь запустить этот код.Исключенное транзакцией исключение при выполнении обновления для запроса обновления JPQL

Ошибка:

javax.persistence.TransactionRequiredException: executeUpdate не поддерживается для объекта запроса, полученного посредством нетранзакционного доступа управляемого контейнером транзакций EntityManager

код: (_ut является объектом UserTransaction)

общественного недействительный setMainCategory (целое число deptId, Целый CatID) {

 try { 
      Query setmain = _entityManager.createNamedQuery("Category.setAsMain"); 
      Query removeMain = _entityManager.createNamedQuery("Category.removeMain"); 
      setmain.setParameter("categoryId", catId); 
      Department d; 
      d=_entityManager.find(Department.class, deptId); 
      removeMain.setParameter("department", d); 
      _ut.begin(); 
      removeMain.executeUpdate(); 
      _ut.commit(); 
      _ut.begin(); 
      setmain.executeUpdate(); 
      _ut.commit(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

У меня есть другие функции, которые идентичны в реализации, и они не бросают эту ошибку.

Любые предложения были бы весьма полезными.

Спасибо.

ответ

1

Проблема возникает не из реализации вашего метода, а из контекста выполнения.
Весь метод, который обновляет базу данных, должен быть выполнен в рамках открытой транзакции. Способ, которым вы гарантируете, зависит от способа управления транзакциями. Если транзакции управляются пользователем, вам необходимо явно получить и присоединиться к существующей транзакции или открыть новую. Если это управляемое контейнером, просто добавьте аннотацию @transactional к вашему методу или убедитесь, что в вашей иерархии вызовов есть аннотация.

Здесь вы используете транзакции, управляемые пользователем, в контексте транзакций, управляемых контейнером (см. «Управляемый транзакцией EntityManager» в сообщении об ошибке). Вам не следует начинать и совершать/откатываться от транзакций. Если вы хотите сделать это, просто получите управляемый приложением EntityManager, чтобы иметь возможность правильно обращаться к транзакциям JTA.

cf. http://docs.oracle.com/cd/E19226-01/820-7627/bnbqy/index.html

0

В соответствии с сообщением об ошибке, я думаю, причина в том, что ваш порядок транзакций, вы не получили Департамент d в транзакции, поэтому инструкция d отделяется, затем вы хотите прямо обновить ее, что будет изменить заявление на управляемый, JPA не может этого сделать. просто переместите код поиска в транзакции, я думаю, все будет хорошо.

+0

Я согласен, что это, вероятно, исправить свою ошибку, но я до сих пор говорят, что он должен использовать @Transactional с управляемой контейнером EntityManager – Gab

+0

Да, точно. Но я думаю, что проект может быть устаревшим проектом, который стоит слишком много, чтобы перейти к использованию аннотации. – OQJF

3

Вы используете EntityManager, чтобы получить именованные запросы, а также с помощью (то, что я думаю) впрыскивается UserTransaction.

Посмотрите, что в сообщении об ошибке указано «... Объект запроса, полученный посредством не-транзакционного доступа ...». Это означает, что вы получаете «NamedQuery» через не транзакционный доступ, так как EntityManager не находится в той же транзакции, что и _ut. Итак, вы сначала присоединитесь к EntityManager к UserTransaction, затем вы получите и выполните запрос.

Наконец ваш блок должен выглядеть следующим образом:

@PersistenceContext(unitName = "myPU") 
EntityManager em; 

@Inject 
UserTransaction ut; 

public void doSomeStuff() 
{ 
    ut.begin(); 
    em.joinTransaction(); 

    em.createNamedQuery("query1").executeUpdate(); 

    ut.commit(); 
} 
Смежные вопросы