私はSpring/JPA/Hibernateを初めて使いました。簡単に聞こえるかもしれませんが、現実はそうではありませんでした。私はいくつかの助けを使うことができます。
子エンティティのリストを保持する親エンティティがあります。議論を簡単にするために、これらを使用します。
@Entity
public class Parent {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@OneToMany(fetch=FetchType.EAGER, cascade = CascadeType.ALL, mappedBy="parent")
private List<Child> children= new ArrayList<Child>();
etc...
}
@Entity
public class Child {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@ManyToOne
private Parent parent;
etc...
}
@Repository
public interface ParentRepository extends JpaRepository<Parent, Long> {};
ラウンド 1 では、新しい親と新しい子を作成し、子を親のリストに追加して、子に親を設定します。親を保存すると、子も保存されます。
@Transactional(propagation=Propagation.REQUIRES_NEW)
void create() {
Parent parent = new Parent();
Child child = new Child();
parent.add(child);
child.setParent(parent);
parent = repository.save(parent);
}
ラウンド 2 では、新しい子を追加します。
@Transactional(propagation=Propagation.REQUIRES_NEW)
void update() {
Parent parent = repository.findOne(parentID);
Child newChild = new Child();
newChild.setParent(parent);
parent.add(newChild);
parent = repository.save(parent);
}
ただし、今回は新しい子が永続化されることはありません。
CascadeType、@GeneratedValue GenerationType、@Transactional Propagation タイプのほぼすべてのバリエーションを試しました...
これを休止状態で追跡すると(痛い!)、ここに私が見つけたものがあります:
- 2 回目に保存する場合、問題は 2 番目の (新しい) 子にあります。
- 問題は、親の子リストを永続化するときに、新しい子が (まだ) EntityManager にないため、一時的であると見なされることです。
- その結果、効果的にチェーンを null として渡され、次のようになります。
org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing thetransaction at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:521) ... Caused by: javax.persistence.RollbackException: Error while committing the transaction at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:92) at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:512) ... Caused by: org.hibernate.AssertionFailure: collection [null] was not processed by flush() at org.hibernate.engine.spi.CollectionEntry.postFlush(CollectionEntry.java:225) ...
- 私の実際のコードでは、「子」にも子エンティティのマップがあることが関連している可能性があります。この「値」は、「一時的な」不正流用により null として渡されるものです。
- 私は repository.saveAndFlush() を使用して、デバッグのために物事を同期させてきました。.save() だけを使用すると、 @PreUpdate EntityListener が呼び出されますが、 @PostUpdate リスナーは呼び出されません。
- 少なくとも親を永続化する前に、子が永続化されるか、ID が与えられただけであれば、問題はないようです。しかし、それを手動で行うのも逆効果のようです。それでも、それが私が考えることができる唯一の選択肢です。
読んでくれてありがとう。どんな助けでも大歓迎です!