没有事务的JPA更新查询-事务是强制性的吗?

时间:2018-06-21 15:46:55

标签: java hibernate jpa transactions

我正在尝试通过JPA的本机查询进行插入,但是我不想创建事务:

Query query = em.createNativeQuery("INSERT INTO person (id, firstname, lastname) VALUES ('1','Ronnie','Dio')");
int count = query.executeUpdate();

这以TransactionRequiredException结尾:

javax.persistence.TransactionRequiredException: Executing an update/delete query

at org.hibernate.ejb.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:99)

但是,如果我解开Hibernate会话并执行相同的查询-它会起作用:

Session session = em.unwrap(Session.class);
Query query = session.createSQLQuery("INSERT INTO person (id, firstname, lastname) VALUES ('1','Ronnie','Dio')");
int count = query.executeUpdate();

所以我的问题是-第一个样本中我做错了什么?在JPA中执行插入/更新/删除查询真的需要事务吗? 如果是的话,是否有任何指向文档的链接清楚地说明了该链接?如果不是,我在做什么错?

2 个答案:

答案 0 :(得分:2)

似乎您正在构建的应用程序无法在支持 JTA 托管事务的容器中运行。在这样的环境中,您必须自己处理/管理事务,即必须控制何时打开,提交或回滚事务。这种情况称为资源本地实体管理器

在官方JPA 2.2 specification(第345页)的 7.5.2 资源本地的EntityManagers 部分中,我们发现:< / p>

  

一个实体管理器,其事务由应用程序通过EntityTransaction控制   API是本地资源实体管理器。资源本地实体管理器事务已映射   持久性提供程序在资源上进行资源事务处理。资源本地实体经理   可能使用服务器或本地资源连接到数据库,并且不知道JTA的存在   可能有效或无效的交易

在规范文档中进一步给出了EntityTransaction接口。它可以让您打电话

  1. begin()“开始资源交易”
  2. commit()“提交当前资源事务,写任何 取消对数据库的更改。”
  3. rollback()“回滚当前资源事务。” 以防在提交更改时数据库方面出现问题。

那是理论部分。 对于您的代码示例,您可能需要对其进行如下更改:

EntityTransaction tx = null;
try {
    tx = em.getTransaction();
    // start a new transaction, i.e. gather changes from here on...
    tx.begin();

    // do your changes here
    Query query = em.createNativeQuery("INSERT INTO person (id, firstname, lastname) VALUES ('1','Ronnie','Dio')");
    int count = query.executeUpdate();

    // write changes to database via commit
    tx.commit();
} catch(RuntimeException re) {
    if(tx != null && tx.isActive()) {
        // ensure no semi-correct changes are pending => cleanup
        tx.rollback();
    }
    // handle exception, log it somewhere...
}

这应避免遇到TransactionRequiredException。此外,您应该避免使用createNativeQuery,因为您滥用了对象关系映射器(ORM)的基本概念,即,映射器会为您将对象转换为元组,反之亦然。通常,这应该可以减轻为大量域实体编写插入/更新查询的麻烦。

查看上面链接的规范文档的 3.1.1 EntityManager接口部分(第65页)并使用这些方法

  • persist(..)-“使实例具有托管性和持久性。”
  • merge(..)-“将给定实体的状态合并到当前持久性上下文中。”

有关这两种方法的区别的更多信息,请参见帖子herehere

希望有帮助。

答案 1 :(得分:0)

我建议您为人员创建一个JPA实体,而不是创建本机查询,并且使用JPARepository,您可以为该人员使用save方法插入任何记录。

相关问题