我有一个包含多对一关系的 JPA 持久对象模型:一个Account有很多Transactions. ATransaction有一个Account。
Account
Transactions
Transaction
这是代码片段:
@Entity public class Transaction { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @ManyToOne(cascade = {CascadeType.ALL},fetch= FetchType.EAGER) private Account fromAccount; .... @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;
我能够创建一个Account对象,向它添加事务,并Account正确地保存该对象。但是,当我 使用现有的已持久化 Account 创建事务并持久 化 Transaction 时,出现异常:
引起:org.hibernate.PersistentObjectException:分离实体传递给持久化:com.paulsanwald.Account at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:141)
所以,我能够持久化一个Account包含事务的事务,但不能持久化一个具有Account. 我认为这是因为Account可能没有附加,但这段代码仍然给了我同样的异常:
if (account.getId()!=null) { account = entityManager.merge(account); } Transaction transaction = new Transaction(account,"other stuff"); // the below fails with a "detached entity" message. why? entityManager.persist(transaction);
如何正确保存Transaction与已持久化Account对象关联的 , ?
这是一个典型的双向一致性问题。在此链接以及此链接中对此进行了很好的讨论。
根据前面 2 个链接中的文章,您需要在双向关系的两侧修复您的设置器。一侧的示例设置器在此链接中。
许多方面的示例设置器在此链接中。
更正设置器后,您希望将实体访问类型声明为“属性”。声明“属性”访问类型的最佳实践是将所有注释从成员属性移动到相应的 getter。一个重要的词是不要在实体类中混合“字段”和“属性”访问类型,否则 JSR-317 规范未定义行为。