【发布时间】:2013-02-20 21:25:51
【问题描述】:
我有一个对象列表。它们是 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 个位置对象,而第 54 个对象有问题并引发异常。将有 53 条记录插入到数据库中。我想要的是:他们都必须先成功,然后才能成功。
我正在使用最新最好的 Java EE6、EJB 3.x 和 JPA 2。我的 persistence.xml 使用 JTA。
<persistence-unit name="myPersistenceUnit" transaction-type="JTA">
而且我喜欢 JTA。 我不想停止使用 JTA。 90% 的时间 JTA 完全按照我的意愿去做。但在这种情况下,我似乎没有。
我对 JTA 的理解一定是不准确的,因为我一直认为 EJB 方法的开始和结束标记了 JTA 事务的边界(假设只有一种方法在起作用,如上所示)。按照我的逻辑,直到 for 循环完成并且方法返回,事务才会结束,然后记录被持久化。
我正在使用 SqlServer 2008 的 JTDS 驱动程序。也许数据库不想在不立即提交的情况下插入记录。实体 id 定义如下:
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
我检查了规范,在 JTA 环境中调用各种“UserTransaction”或“getTransaction()”方法是不合适的。
那我该怎么办? 谢谢。
【问题讨论】:
-
那么,有什么问题呢?如果第 54 条记录导致抛出异常会怎样?你做过测试吗?您的假设是正确的:在运行时异常的情况下,您将有一个回滚。
-
我想我最初的问题不够清楚。我已经对此进行了测试;一遍又一遍地。如果第 54 条记录失败,之前的 53 条记录仍会插入到数据库中。这是一个问题,因为我不希望将这 53 条记录插入到数据库中。
-
第54条记录怎么失败?它会抛出异常吗?哪一个?
-
Location 对象包含许多必填字段,并且必须包含唯一名称。如果必填字段不存在或出现非唯一名称,则可能会发生故障。从理论上讲,这些类型的问题会在尝试插入之前被捕获(通过使用“前门”验证器类),但情况并非总是如此。