当我尝试运行此代码时出现此错误。
错误:
javax.persistence.TransactionRequiredException:通过容器管理的事务性EntityManager的非事务性访问获得的Query对象不支持executeUpdate
代码:(_ ut是UserTransaction对象)
public void setMainCategory(Integer deptId,Integer 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();
}
}
我有其他功能在实现上是相同的,他们不会抛出此错误。
任何建议都将不胜感激。
感谢。
答案 0 :(得分: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();
}
答案 1 :(得分:1)
问题不是来自您的方法实现,而是来自您的执行上下文。
所有更新数据库的方法必须在打开的事务中执行。确保这一点的方式取决于您管理事务的方式。如果事务是用户管理的,则必须显式检索并加入现有事务或打开新事务。如果它是容器管理的,只需在方法上添加@transactional
注释,或者确保调用层次结构中有一个方法保存注释。
这里,您在容器管理的事务上下文中使用用户管理的事务(请参阅错误消息中的“容器管理的事务EntityManager”)。你不应该这样开始并自己提交/回滚事务。如果您想这样做,只需检索应用程序管理的EntityManager即可正确访问JTA事务。
比照http://docs.oracle.com/cd/E19226-01/820-7627/bnbqy/index.html
答案 2 :(得分:0)
根据错误信息,我认为原因是你的交易订单,你没有在交易中获得部门d,所以d的声明是分离的,那么你想直接更新它会改变它声明要管理,JPA不能这样做。只需在事务中移动查找代码,我认为没问题。