当前位置: 首页 > 知识库问答 >
问题:

JPA与JTA如何在一个事务中持久化多个实体

宿楚青
2023-03-14

我有一个物品清单。它们是JPA“位置”实体。

List<Location> locations;

我有一个无状态EJB,它在列表中循环并持久化每一个。

public void createLocations() {
    List<Locations> locations = getListOfJPAManagedLocationEntities(); // I'm leaving out the details of this because it has nothing to do with the issue

    for(Location location : locations) {
        em.persist(location);
    }
}

代码运行良好。我没有任何问题。然而,问题是:我希望这是一个全有或全无的交易。当前,每次通过for循环,persist()方法都会在数据库中插入一个新行。假设我有100个location对象,而第54个对象有问题,并且抛出了一个异常。将有53条记录插入数据库。我想要的是:在任何一个成功之前,他们必须全部成功。

我使用的是Java EE6、EJB3.x和JPA2的最新和最好的版本。我的persistence.xml使用JTA。

<persistence-unit name="myPersistenceUnit" transaction-type="JTA">

我喜欢JTA。我不想停止使用JTA。90%的情况下,JTA完全按照我的要求去做。但在这种情况下,我似乎没有。

我对JTA的理解肯定是不准确的,因为我一直认为EJB方法的开始和结束标志着JTA事务的边界(假设只有一个方法在使用,如我上面所示)。按照我的逻辑,事务不会结束,直到for-loop完成并且方法返回,然后在这一点上记录被持久化。

我正在使用SQLServer2008的JTDS驱动程序。也许数据库不想在没有立即提交记录的情况下插入记录。实体id的定义如下:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)

我已经检查了规范,在JTA环境中调用各种“userTransaction”或“getTransaction()”方法是不合适的。

共有1个答案

司马狐若
2023-03-14

如果使用JTA和容器管理的事务,会话EJB方法调用的默认行为是在事务中运行(就像用@TransactionAttribute(TransactionAttributeType.Required)对其进行注释。这意味着您的代码已经在事务中运行,并且将执行您所期望的操作:如果在第54行发生异常,则将回滚之前插入的所有行。您可以通过在循环中的某个点抛出一个异常来测试它。请注意,如果抛出一个由方法声明的检查异常,则可以指定该异常发生时容器应执行的操作。您需要使用@applicationexception(rollback=true)注释异常类。

 类似资料:
  • 我试图集成Spring和JSF,我坚持使用对象。我不想处理事务(begin-commit等) 经过一些谷歌,我可以找到一个答案,给我需要在这个链接 我使用eclipselink作为ORM和Oracle 11g数据库,并使用带有Maven的Glassfish Server3.1。我更喜欢Spring配置的注释。我用 相关类中的注释。我的名称是E_DefterManagementPU,我的事务类型是J

  • 我有一个实体,代表客户发送的订单,这个订单可能会在电话上与客户讨论后更新,但客户发送的初始订单必须保持不更新。我如何可以保持同一实体两次,是否有效的使用深层克隆。我试图分离实体以便持久化上下文持久化一个新的,但是持久化上下文仍然在更新第一个条目。

  • 谢谢 ----更新----

  • 我有一个事务性方法,在它的内部,一个实体被实例化,并使用persist方法插入到Hibernate上下文中。然后更改实体的某些属性(因此它将反映在数据库中)。如果对实体调用detach方法,然后更改实体的某些属性,会发生什么情况。当方法完成(和事务提交)时,Hibernate是否会插入实体并将属性更新到分离调用之前的点? 例如:

  • 最后的修正:由于Vlad的回答,我能够更新代码以使用以下内容(只需确保您还定义了bean):

  • 我有一个问题,如果我的服务上有一个客户端调用两个方法,它就会失败,因为第二个方法中的事务没有与之关联的会话。但是,如果我将这两种方法组合到服务中,并从客户机代码中调用其中一种方法,它就会成功。 谁能给我解释一下为什么会这样? 考虑下面的代码: 所以这里发生的事情是,在我的客户机代码中(它不知道事务),如果我调用#getChildrenFor(id),我就没事了。但如果我打电话: 然后hiberna