ドキュメントには要素のリストがあり、これらの要素は Element のサブクラスです。この例では Link です。Link は、Resource に対して @OneToOne 関係を持っています。オブジェクト グラフ全体を 1 ステップで作成する限り、すべてがうまくいきました。
ここでコードを変更して、Resource のインスタンスを作成し、それを保持してクライアント (Web、JSON にシリアル化されたオブジェクト) に渡します。クライアントはドキュメントのインスタンスを作成し、既存のリソースにリンクを追加します。その後、新しい Document を永続化しようとします。
この時点で、JPA は既存のリソースを同じ ID で永続化しようとするため、操作は失敗します。これは、リソースが切り離されており、JPA がこのエンティティをマージする必要があるか永続化する必要があるかを判断する方法がないために発生すると思います。CascadeType.ALL を削除して CascadeType.MERGE に置き換えると、リソースがまったく更新されないことを除いて、すべて問題ありません。
基本的にワークフローは次のとおりです。
- リソースの作成と永続化
- 取引を残す
- 取引開始
- リンクと (切り離された) リソースを含むドキュメントを作成する
- エラー
JPA 構成に問題はありますか (エンティティーを見てください)。ヒントをいただければ、いつかビールを差し上げたいと思います... :-) TYIA。
私たちのセットアップは、EclipseLink 2.4.1、Spring Data JPA 1.3.0 (@Repository を使用)、PostgreSQL 9.2 です。
書類:
@Entity
public class Document implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
@OrderColumn
@JoinColumn(name = "document_id")
private List<Element> elements = new ArrayList<Element>();
// getters and setters
}
エレメント:
@Entity
@Inheritance(strategy = InheritanceType.
public class Element implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "document_id", insertable = false, updatable = false)
private Document document;
// getters and setters
}
リンク:
@Entity
public class Link extends Element {
@Column
private String appearance;
@Column
private String referenceType;
@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
private Resource resource;
// getters and setters
}
リソース:
@Entity
public class Resource {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@Column
private String uri;
// getters and setters
}