2

ドキュメントには要素のリストがあり、これらの要素は 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
}
4

2 に答える 2

0

EclipseLink の実装でバグを引き起こしたと思います。同じ問題に出くわした人のために、いくつかの役立つリンクを次に示します。

http://chandanpandey.com/2012/12/22/persisting-a-detached-entity-in-jpa https://bugs.eclipse.org/bugs/show_bug.cgi?id=324941

回避策は、CascadeType.ALL を許可しないことでした。

@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)

代わりに使用する

@OneToOne(cascade = {CascadeType.MERGE, CascadeType.REFRESH, CascadeType.REMOVE, CascadeType.DETACH}, orphanRemoval = false)

orphanRemoval を無効にします。これには確かにいくつかの欠点があり、これがEclipseLinkの将来のリリースで修正されることを願っています(バグレポートは2010年のものであるため、これは疑わしいです)。

これが誰にも役立つことを願っています。

于 2013-04-18T07:02:32.457 に答える