gpt4 book ai didi

java - 没有交易的 JPA 更新查询 - 交易是强制性的吗?

转载 作者:行者123 更新时间:2023-11-29 04:18:11 28 4
gpt4 key购买 nike

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

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 session = em.unwrap(Session.class);
Query query = session.createSQLQuery("INSERT INTO person (id, firstname, lastname) VALUES ('1','Ronnie','Dio')");
int count = query.executeUpdate();

所以我的问题是 - 我在第一个示例中做错了什么?在 JPA 中执行插入/更新/删除查询真的需要事务吗?如果是,是否有指向明确指定它的文档的链接?如果不是-我做错了什么?

最佳答案

看起来您正在构建一个不在支持 JTA 管理事务的容器内运行的应用程序。在这样的环境中,您必须自己处理/管理事务,即您必须控制事务何时打开、提交或回滚。此方案称为资源本地实体管理器

在官方的7.5.2 Resource-local EntityManagers部分JPA 2.2 specification (第 345 页)我们发现:

An entity manager whose transactions are controlled by the application through the EntityTransactionAPI is a resource-local entity manager. A resource-local entity manager transaction is mappedto a resource transaction over the resource by the persistence provider. Resource-local entity managersmay use server or local resources to connect to the database and are unaware of the presence of JTAtransactions that may or may not be active

在规范文档的下方,给出了 EntityTransaction 接口(interface)。它允许你调用

  1. begin()“启动资源事务”
  2. commit() to “提交当前资源事务,写入任何对数据库的未刷新更改。”
  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 接口(interface)(第 65 页)部分并使用这些方法

  • persist(..) - “使一个实例得到管理和持久化。”
  • merge(..) - “将给定实体的状态合并到当前持久化上下文中。”

有关两种方法差异的更多信息,请参阅帖子 herehere .

希望对您有所帮助。

关于java - 没有交易的 JPA 更新查询 - 交易是强制性的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50972692/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com