没有事务的JPA更新查询-事务是强制性的吗? [英] JPA update query without transaction - is transaction mandatory?

查看:671
本文介绍了没有事务的JPA更新查询-事务是强制性的吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to do insert via a native query with JPA, but I don't want to create a transaction:

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

这最终会导致TransactionRequiredException:

this ends up with the TransactionRequiredException:

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

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

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

However, if I unwrap the Hibernate session and execute the same query - it works:

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中执行插入/更新/删除查询是否真的需要事务处理? 如果是的话,是否有任何指向文档的链接清楚地说明了该链接?如果不是,我在做什么错?

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? If it is, is there any link to documentation that specifies it clearly? If it's not - what am I doing wrong?

推荐答案

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

It seems you are building an application that does not run inside a container supporting JTA managed transactions. In such an environment, you have to handle/manage transactions for yourself, i.e., 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:

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

An entity manager whose transactions are controlled by the application through the EntityTransaction API is a resource-local entity manager. 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

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

Further down in the spec document the EntityTransaction interface is given. It allows you to call

  1. begin()开始资源交易"
  2. commit()"提交当前资源事务,写任何 取消对数据库的更改."
  3. rollback()回滚当前资源事务." ,以防在提交更改时数据库方面出现问题.
  1. begin() to "Start a resource transaction"
  2. commit() to "Commit the current resource transaction, writing any unflushed changes to the database."
  3. rollback() to "Roll back the current resource transaction." 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...
}

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

This should avoid the TransactionRequiredException you encounter. Moreover, you should avoid the use createNativeQuery, as you are mis-using a fundamental concept of an Object-Relational-Mapper (ORM), i.e. the mapper will transform objects into tuples and vice versa for you. This - in general - should ease the pain of writing insert/update queries for a large amount of domain entities.

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

Have a look into section 3.1.1 EntityManager Interface (p. 65) of the spec document linked above and make use of the methods

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

有关这两种方法的区别的更多信息,请参见此处

For more infos on the difference of both approaches see the posts here and here.

希望有帮助.

这篇关于没有事务的JPA更新查询-事务是强制性的吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆