简体   繁体   English

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

[英]JPA update query without transaction - is transaction mandatory?

I'm trying to do insert via a native query with JPA, but I don't want to create a transaction: 我正在尝试使用JPA通过本机查询进行插入,但是我不想创建事务:

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

this ends up with the TransactionRequiredException: 这以TransactionRequiredException结尾:

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

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

However, if I unwrap the Hibernate session and execute the same query - it works: 但是,如果我解开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();

So my question is - what am I doing wrong in the first sample? 所以我的问题是-我在第一个样本中做错了什么? Is transaction really required to execute insert/update/delete queries in JPA? 在JPA中执行插入/更新/删除查询真的需要事务吗? If it is, is there any link to documentation that specifies it clearly? 如果是的话,是否有任何指向文档的链接清楚地说明了该链接? If it's not - what am I doing wrong? 如果不是,我在做什么错?

It seems you are building an application that does not run inside a container supporting JTA managed transactions. 似乎您正在构建的应用程序无法在支持JTA管理的事务的容器中运行。 In such an environment, you have to handle/manage transactions for yourself, ie, you have to control when transactions are opened, committed or rolled back. 在这样的环境中,您必须自己处理/管理事务,即,您必须控制何时打开,提交或回滚事务。 This scenario is referred to as resource-local entity manager . 此方案称为资源本地实体管理器

In section 7.5.2 Resource-local EntityManagers of the official JPA 2.2 specification (p. 345) we find: 在官方JPA 2.2规范 (第345页)的7.5.2 资源本地EntityManager中,我们发现:

An entity manager whose transactions are controlled by the application through the EntityTransaction API is a resource-local entity manager . 由应用程序通过EntityTransaction API控制事务的实体管理器是本地资源实体管理器 A resource-local entity manager transaction is mapped to a resource transaction over the resource by the persistence provider. 持久性提供程序将资源本地实体管理器事务映射到资源上的资源事务。 Resource-local entity managers may use server or local resources to connect to the database and are unaware of the presence of JTA transactions that may or may not be active 资源本地实体管理器可能使用服务器或本地资源连接到数据库,并且不知道是否存在可能处于活动状态的JTA事务

Further down in the spec document the EntityTransaction interface is given. 在规范文档的EntityTransaction ,给出了EntityTransaction接口。 It allows you to call 它可以让你打电话

  1. begin() to "Start a resource transaction" begin()“启动资源事务”
  2. commit() to "Commit the current resource transaction, writing any unflushed changes to the database." commit()更改为“提交当前资源事务,将所有未更改的更改写入数据库。”
  3. rollback() to "Roll back the current resource transaction." rollback()“回滚当前资源事务。” in case something went wrong on the database side while committing changes. 如果在提交更改时数据库方面出了点问题。

That's for the theory part. 这是理论部分。 For your code example, you might want to change it as follows: 对于您的代码示例,您可能需要按如下所示进行更改:

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...
}

This should avoid the TransactionRequiredException you encounter. 这应该避免您遇到的TransactionRequiredException Moreover, you should avoid the use createNativeQuery , as you are mis-using a fundamental concept of an Object-Relational-Mapper (ORM), ie the mapper will transform objects into tuples and vice versa for you. 此外,您应该避免使用createNativeQuery ,因为您误用了Object-Relational-Mapper(ORM)的基本概念,即,映射器会为您将对象转换为元组,反之亦然。 This - in general - should ease the pain of writing insert/update queries for a large amount of domain entities. 通常,这应该可以减轻为大量域实体编写插入/更新查询的麻烦。

Have a look into section 3.1.1 EntityManager Interface (p. 65) of the spec document linked above and make use of the methods 请查看上面链接的规范文档的3.1.1 EntityManager接口 (第65页)部分,并使用这些方法

  • persist(..) - "Make an instance managed and persistent." persist(..) - “使实例成为托管的和持久的。” or 要么
  • merge(..) - "Merge the state of the given entity into the current persistence context." merge(..) - “将给定实体的状态合并到当前持久性上下文中。”

For more infos on the difference of both approaches see the posts here and here . 有关这两种方法的区别的更多信息,请参见此处此处的文章。

Hope it helps. 希望能帮助到你。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM