web-dev-qa-db-ja.com

JPA OneToManyおよびManyToOneスロー:エンティティ列のマッピングで列を繰り返します(insert = "false" update = "false"でマップする必要があります)

私は3つのクラスを持っています。名前の1つはUserで、このユーザーには他のクラスインスタンスがあります。このような;

public class User{
    @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL)
    public List<APost> aPosts;

    @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL)
    public List<BPost> bPosts;
}




   public class BPost extends Post {

    @ManyToOne(fetch=FetchType.LAZY)    
    public User user;
 }

    public class APost extends Post {

     @ManyToOne(fetch=FetchType.LAZY) 
     public User user;
 }

このように動作しますが、dbにemtyテーブルを生成します。外部キーを含む必要があります。 mappedByとJoinColumn annotainsを使用しようとすると失敗しました。どうすれば解決できますか?

追加情報:

で変更したとき;

 @ManyToOne(fetch=FetchType.LAZY)
 @JoinColumn(name="id")
 public User user;

そして

 @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="id")
 public List<APost> aPosts;

私は得ています

JPAエラーが発生しました(EntityManagerFactoryを構築できません):エンティティのマッピングで繰り返される列:models.post.APost列:id(insert = "false" update = "false"でマッピングする必要があります)

最終編集:最後に、私はJPA注釈について全く間違っていました。 :(私が変わるとき

@OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="id")

@OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="user")

そして

@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="user_id")

エバーシングは大丈夫です。 :)

49
Ömer Faruk AK

この記事 と私の本 High-Performance Java Persistence で説明したように、単方向の@OneToManyアノテーションは使用しないでください。 :

  1. 非効率的なSQLステートメントを生成します
  2. DBインデックスのメモリフットプリントを増やす余分なテーブルを作成します

さて、最初の例では、両方の側が関連付けを所有しており、 これは悪い です。

@JoinColumn@OneToMany側にアソシエーションを担当させますが、それは間違いなく最良の選択ではありません。したがって、@OneToMany側では常にmappedBy属性を使用してください。

public class User{
    @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="user")
    public List<APost> aPosts;

    @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="user")
    public List<BPost> bPosts;
}

public class BPost extends Post {

    @ManyToOne(fetch=FetchType.LAZY)    
    public User user;
}

public class APost extends Post {

     @ManyToOne(fetch=FetchType.LAZY) 
     public User user;
}
28
Vlad Mihalcea

あなたの質問(「空のテーブル」などの意味、またはmappedByJoinColumnがどのように機能しなかったのか)について私は本当に知りません。

双方向の関係を作ろうとしていたと思います。

最初に、どちらの側が関係を「所有する」かを決定する必要があります。 Hibernateは、その側に関係ベースをセットアップします。たとえば、Post側にリレーションシップを所有させると仮定すると(例を単純化するために、物事を適切に保つために)、マッピングは次のようになります。

(構文が正しいことを望みます。私はメモリだけでそれらを書いています。しかし、アイデアはうまくいくはずです)

public class User{
    @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="user")
    private List<Post> posts;
}


public class Post {
    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="user_id")
    private User user;
}

これにより、Postのテーブルには、関係を格納する列user_idが含まれます。 Hibernateは、userPostによって関係を取得しています(postsUserの代わりに。Postuserがあるが、Userpostsがない場合、違いに気付くでしょう)。

mappedByに言及しましたが、JoinColumnは機能していません。しかし、これは実際には正しい方法だと思います。このアプローチがうまくいかない場合は教えてください。問題についてもう少し情報を提供してください。この問題は他の何かが原因だと思います。


編集:

mappedByの使用に関する少し余分な情報は、最初は通常混乱を招くためです。 mappedByでは、テーブルの列名ではなく、双方向の関係の反対側に「プロパティ名」を配置します。

65
Adrian Shum