当我尝试运行这段代码时,我得到了这个错误。
错误:
通过容器管理的事务性EntityManager的非事务性访问获取的查询对象不支持javax.persistence.TransactionRequiredException: executeUpdate
代码:(_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();
}
}我还有其他在实现上相同的函数,它们不会抛出这个错误。
任何建议都将不胜感激。
谢谢。
发布于 2015-02-03 05:36:33
您使用了一个EntityManager来获取命名查询,还使用了一个(我认为是)注入的UserTransaction。
可以看到错误消息是“通过非事务性访问获得的...Query对象...”。这意味着您将通过非事务性访问获得"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();
}发布于 2013-04-02 16:49:24
问题不是来自你的方法实现,而是你的执行上下文。
所有更新数据库的方法都必须在打开的事务中执行。您确保这一点的方式取决于您管理事务的方式。如果事务是用户管理的,则必须显式检索并加入现有事务或打开新事务。如果它是容器管理的,那么只需在你的方法上添加@transactional注释,或者确保你的调用层次结构中有一个包含注释的方法。
在这里,您在容器管理的事务上下文中使用用户管理的事务(请参阅错误消息中的“容器管理的事务EntityManager”)。您不应该这样开始并自己提交/回滚事务。如果您想这样做,只需检索一个应用程序管理的EntityManager,以便能够正确地访问JTA事务。
请参阅http://docs.oracle.com/cd/E19226-01/820-7627/bnbqy/index.html
发布于 2013-04-02 17:16:35
根据错误消息,我认为原因是您的事务顺序,您没有在事务中获取部门d,所以d的语句被分离,然后您想要直接更新它,这会将语句更改为托管,JPA无法做到这一点。只需在事务中移动查找代码,我认为这将是好的。
https://stackoverflow.com/questions/15753112
复制相似问题