6

当我尝试运行此代码时出现此错误。

错误:

javax.persistence.TransactionRequiredException:通过容器管理的事务实体管理器的非事务访问获得的查询对象不支持执行更新

代码:(_ut 是一个 UserTransaction 对象)

公共无效 setMainCategory(整数部门 ID,整数 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();
        }
    }

我还有其他实现相同的功能,它们不会抛出此错误。

任何建议将不胜感激。

谢谢。

4

3 回答 3

3

您正在使用 anEntityManager来获取 Named Queries 并且还使用 an (我认为是) injection UserTransaction

看到错误消息是“...Query object getting through non-transactional access...”。这意味着您正在通过非事务性访问获得“NamedQuery”,因为 与EntityManager不在同一个事务中_ut。所以,你首先加入EntityManagerUserTransaction然后你得到并执行查询。

最后,您的块应如下所示:

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

@Inject
UserTransaction ut;

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

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

    ut.commit();
}
于 2015-02-02T21:36:33.207 回答
1

问题不是来自您的方法实现,而是来自您的执行上下文。
所有更新数据库的方法都必须在打开的事务中执行。您确保的方式取决于您管理事务的方式。如果事务是用户管理的,您必须显式检索并加入现有事务或打开一个新事务。如果它是容器管理的,只需@transactional在您的方法上添加注释或确保调用层次结构中有一个方法保存该注释。

在这里,您在容器管理的事务上下文中使用用户管理的事务(请参阅错误消息中的“容器管理的事务实体管理器”)。您不应该这样开始并自己提交/回滚事务。如果您想这样做,只需检索应用程序管理的 EntityManager 即可正确访问 JTA 事务。

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

于 2013-04-02T08:49:24.433 回答
0

根据报错信息,我认为原因是你的交易顺序,你在交易中没有得到部门d,所以d的语句是分离的,然后你想直接更新它,这会将语句更改为托管,JPA 无法做到这一点。只需在事务中移动查找代码,我认为就可以了。

于 2013-04-02T09:16:35.357 回答