【问题标题】:Transaction required exception on execute update for JPQL update queryJPQL 更新查询的执行更新需要事务异常
【发布时间】:2013-03-23 02:21:19
【问题描述】:

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

错误:

javax.persistence.TransactionRequiredException:通过容器管理的事务实体管理器的非事务访问获得的 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();
        }
    }

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

任何建议将不胜感激。

谢谢。

【问题讨论】:

    标签: jpa transactions sql-update jpql entitymanager


    【解决方案1】:

    您正在使用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();
    }
    

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        【解决方案3】:

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

        【讨论】:

        • 我同意这可能会解决他的错误,但我仍然说他应该将@transactional 与容器管理的EntityManager 一起使用
        • 是的,没错。但我认为该项目可能是一个遗留项目,迁移到使用注释的成本太高。
        猜你喜欢
        • 2019-07-16
        • 1970-01-01
        • 2011-02-27
        • 1970-01-01
        • 2011-08-15
        • 2016-02-29
        • 1970-01-01
        • 2016-09-27
        • 2014-07-25
        相关资源
        最近更新 更多