返回

JPA 中使用已持久化 Account 对象保存 Transaction,解决 \

java

JPA 中使用已持久化 Account 对象保存 Transaction

在 JPA 中使用 Hibernate 时,处理具有双向关联的对象(例如 Account 和 Transaction)时可能会出现问题。当尝试保存一个具有已持久化 Account 的新 Transaction 时,可能会出现 "detached entity passed to persist" 错误。这是因为 Hibernate 要求所有要持久化的实体都处于托管状态。

解决办法

有几种方法可以解决此问题:

  • 合并 Account 对象: 使用 EntityManager 的 merge() 方法将 Account 对象与持久化上下文的托管副本合并。这会将 Account 对象附加到持久化上下文中,并确保它在持久化 Transaction 时处于托管状态。
if (account.getId() != null) {
    account = entityManager.merge(account);
}
  • 使用持久化关联: 在创建 Transaction 时,使用 persistence association 创建 Transaction 与 Account 之间的关系,而不是使用新对象。这意味着在创建 Transaction 时,使用 Account 对象的持久化副本,而不是 detached 版本。
Transaction transaction = new Transaction(entityManager.find(Account.class, account.getId()), "other stuff");
  • 使用 cascade 操作: 在 Account 实体类中,使用 CascadeType.PERSIST 作为 @OneToMany 关联的 cascade 选项。这将导致在持久化 Account 时自动持久化 Transaction。
@Entity
public class Account {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @OneToMany(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER, mappedBy = "fromAccount")
    private Set<Transaction> transactions;
}

通过使用这些技术之一,你可以确保在 JPA 中使用已持久化的 Account 对象正确保存 Transaction。

常见问题解答

  • 为什么 detached entity 错误会在 JPA 中发生?
    当尝试持久化一个不在持久化上下文中托管的实体时,就会发生 detached entity 错误。

  • 如何确定实体是否处于托管状态?
    你可以使用 EntityManager.contains() 方法来检查实体是否处于托管状态。

  • 我应该何时使用 merge() 方法?
    当需要将一个 detached 实体附加到持久化上下文中时,应该使用 merge() 方法。

  • 我应该何时使用持久化关联?
    当在创建新实体时需要使用现有实体时,应该使用持久化关联。

  • 我应该何时使用级联操作?
    当需要在持久化父实体时自动持久化子实体时,应该使用级联操作。