我正在尝试通过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中执行插入/更新/删除查询真的需要事务吗? 如果是的话,是否有任何指向文档的链接清楚地说明了该链接?如果不是,我在做什么错?
答案 0 :(得分:2)
似乎您正在构建的应用程序无法在支持 JTA 托管事务的容器中运行。在这样的环境中,您必须自己处理/管理事务,即必须控制何时打开,提交或回滚事务。这种情况称为资源本地实体管理器。
在官方JPA 2.2 specification(第345页)的 7.5.2 资源本地的EntityManagers 部分中,我们发现:< / p>
一个实体管理器,其事务由应用程序通过
EntityTransaction
控制 API是本地资源实体管理器。资源本地实体管理器事务已映射 持久性提供程序在资源上进行资源事务处理。资源本地实体经理 可能使用服务器或本地资源连接到数据库,并且不知道JTA的存在 可能有效或无效的交易
在规范文档中进一步给出了EntityTransaction
接口。它可以让您打电话
begin()
到“开始资源交易” commit()
到“提交当前资源事务,写任何
取消对数据库的更改。” 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(..)
-“将给定实体的状态合并到当前持久性上下文中。” 有关这两种方法的区别的更多信息,请参见帖子here和here。
希望有帮助。
答案 1 :(得分:0)
我建议您为人员创建一个JPA实体,而不是创建本机查询,并且使用JPARepository,您可以为该人员使用save方法插入任何记录。