JPA - 持久化对象时何时使用 getTransaction()

Posted

技术标签:

【中文标题】JPA - 持久化对象时何时使用 getTransaction()【英文标题】:JPA - When to use getTransaction() when persisting objects 【发布时间】:2012-01-17 20:38:15 【问题描述】:

我最近开始在 Google App Engine 上使用 JPA。在阅读一些示例时,我注意到对象的持久化方式存在一些变化。在一种情况下,我见过这样的事情:

entityManager.getTransaction().begin();
entityManager.persist(object);
entityManager.getTransaction().commit();

在其他情况下,我看不到getTransaction() 的使用。我只是看到entityManager.persist(object)。什么时候使用getTransaction()比较合适?

【问题讨论】:

【参考方案1】:

如果您使用容器管理的EntityManager,那么您使用的是 JTA 事务。因此,您不需要(更准确地说 - 您不能)干扰使用 entityManager.getTransaction() 获取的 EntityManager 的事务。 JTA 启动并提交您的事务。

如果您使用应用程序管理 EntityManager 并且您不想参与 JTA 事务,那么您需要自己管理它们(称为资源本地实体管理器)。

大多数情况下,与EntityManager.getTransaction() 一起使用的应用程序托管EntityManager 用于Java SE 环境。

编辑:您可能对JPA 2.0 specification 中的7.5 控制交易部分感兴趣。

【讨论】:

从未与 GAE 合作过 - 认为这是更多以 JPA 事务为中心的问题。感谢您的澄清。 即使从数据库中获取实体,我们是否也需要获取事务...使用 entitymanager.find 方法...只是好奇..因为我什至看不到一个示例..在哪里进行交易。 begin() 在 entitymanger.find 方法之前...:) :)【参考方案2】:

当您在应用程序中显式处理事务时,您会使用getTransaction()。另一方面,如果您让容器为您处理事务,则无需显式地开始/结束事务。本质上,我们处理的是Container Managed Transactions (CMT) 和Bean Managed Transactions (BMT) 之间的区别。

一般来说,当您需要对事务处理进行更多控制时,或者当有其他技术要求(例如,两阶段提交、分布式事务、XA 事务)无法满足时,您会使用 BMT使用 CMT。此外,当您的应用程序部署在应用程序服务器之外并依赖于 Java SE 时,您将使用 BMT。

【讨论】:

【参考方案3】:

在 GAE 中没有 Java EE/JTA,因此请忽略 bean 管理事务 (BMT) 和容器管理事务 (CMT) 等术语。

您的工作要么是事务性的(您希望多个对象一次进入数据存储区,或者全部失败 - 这是您使用 getTransaction() 的地方),要么是非事务性的(所有对象都一个接一个地进入数据存储区,并且一个persist的失败不会影响其他人——这就是你调用persist()/merge()/remove())的地方。

【讨论】:

GAE 中有 Java EE 的一些部分,只是没有完整的配置文件。例如,JPA 是一个 Java EE API,但它的行为“有点不同”。【参考方案4】:

Google App Engine 有其事务管理 (https://developers.google.com/appengine/docs/java/datastore/transactions),但 JPA 事务接口不了解 GAE 的一些底层功能(即实体组)。

因此,由您的应用程序决定在事务中执行哪些操作,哪些不执行。 您应该放入必须以原子方式执行的事务操作。

请记住,在事务中执行级联操作和关系操作是最佳实践,因为 JPA 可能会触发许多查询,并可能导致数据不一致的情况。

使用 JPA2 的事务示例:

import javax.persistence.EntityTransaction;


EntityTransaction txn = em.getTransaction();
txn.begin();
try 
    //do something with your database
    txn.commit();
 
finally 
   if (txn.isActive())
      txn.rollback(); 

【讨论】:

以上是关于JPA - 持久化对象时何时使用 getTransaction()的主要内容,如果未能解决你的问题,请参考以下文章

JPA 持久性和 Hibernate javassist 对象

何时使用/不使用,@OneToOne 和 @ManyToOne

JPA

java中配置JPA方法

使用 Hibernate 和 JPA 持久化 JSON 对象

使用没有 em.flush() 的 JPA 持久化深度对象图