0

「ユーザーAはユーザーBに従う」、「ユーザーAはユーザーBの友達になりたい」など、ユーザーとユーザーとの関係を設計しようとしています。Hibernate @OneToMany関係マッピング

私はUserクラスを持って、そしてそれが設計されている方法は、次のようになります。

@Entity 
public class User{ 
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER) 
    List<User> followers; 
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER) 
    List<User> following; 
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER) 
    List<User> friendRequests; 
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER) 
    List<User> requesting; 
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER) 
    List<User> friends; 

} 

は、私は2つの問題に実行しています:

  • Hibernateは私に同時にフェッチすることはできません複数の袋を与えています問題
  • 私はFetchType.EAGERを削除するか、Listの代わりにSetに変更すると言いましたが、その結果、私はField doe sn'tデフォルト値

私は関係が適切に定義されていないという感じを持っているを持っている、そして今、私は唯一のユーザーテーブル、およびUser_Userテーブルを参照してくださいので、また、私は、複数のテーブルを見てする必要があります。


更新

以下は3台、友人、フォロワー、およびリクエスタを作成します。これは5テーブルに比べて幾分最適化されていますか?そして、Mr.J4mesが提案したものと比較して、これにはどんな利点がありますか?

@ManyToMany 
@JoinTable(name = "followers", joinColumns = @JoinColumn(name = "followerId"), inverseJoinColumns = @JoinColumn(name = "userId")) 
private List<User> followers; 
@ManyToMany 
@JoinTable(name = "followers", joinColumns = @JoinColumn(name = "userId"), inverseJoinColumns = @JoinColumn(name = "followerId")) 
private List<User> following; 
@ManyToMany 
@JoinTable(name = "friends", joinColumns = @JoinColumn(name = "userId"), inverseJoinColumns = @JoinColumn(name = "friendId")) 
private List<User> friends; 
@ManyToMany 
@JoinTable(name = "requesters", joinColumns = @JoinColumn(name = "requesterId"), inverseJoinColumns = @JoinColumn(name = "userId")) 
private List<User> friendRequests; 
@ManyToMany 
@JoinTable(name = "requesters", joinColumns = @JoinColumn(name = "userId"), inverseJoinColumns = @JoinColumn(name = "requesterId")) 
private List<User> requesting; 

答えて

1

まず、機能を実装するには、@OneToManyの代わりに@ManyToManyを使用する必要があります。これは次のようになります。

@Entity 
public class User implements Serializable { 
    @ManyToMany(mappedBy="followers") 
    @JoinTable(name="followingTable") 
    private Set<User> following; 
    @ManyToMany 
    @JoinTable(name="followerTable") 
    private Set<User> followers; 
    @ManyToMany(mappedBy="friendRequests") 
    @JoinTable(name="requestingTable") 
    private Set<User> requesting; 
    @ManyToMany 
    @JoinTable(name="friendRequestTable") 
    private Set<User> friendRequests; 
    @ManyToMany 
    private Set<User> friends; 
} 

あなたの関係は私にとって双方向性のようです。@OneToManyを使用すると、C has 2 followers A and B = A and B only follows Cを意味します。しかし、実際には、1人は多くの人に従うことができ、1人には多くの人が従うことができます。つまり、A and B can also follow Dです。

さらに、cascadeType.ALLを使用しないでください。そのカスケードポリシーは、あるユーザーが自分のアカウントを削除し、データベース内の対応するエントリーを削除すると、彼のすべての友達なども削除されることを意味します。

+0

'Hibernate:値(?、?)にの値を挿入User_User(requesting_id、friendrequests_id)2012-01-12 00:52:04,900 WARN [SqlExceptionHelper] SQLエラー:1364、SQLState:HY000 2012-01-12 00:52 :04,901 ERROR [SqlExceptionHelper]フィールド 'following_id'にデフォルト値がありません。 ' これは問題です。私は、user_userテーブルが必要ではない5列を持っていると思います。そして、私は、どちらかの要求を更新する必要があるだけで、もう1つは設定されていないため、この問題が発生します。 – HeavenAgain

+0

@ user1129335私が言及したようにあなたの関係が本当に双方向であるなら、あなたは選択肢がありません。あなたの問題を解決するために、私は '@ JoinTable'アノテーションを使って答えを更新しました。この注釈は、あなたの関係に5つの異なる表を作成するのに役立ちます。 –

+0

「cascadeType.ALL」の効果は、ユーザが自分のアカウントを削除した場合、実際にゴーストユーザを望んでいないため、希望の効果のように聞こえるという2つのことがあります。しかし、それはポイントのほかにあります。私はこの[post](http://stackoverflow.com/questions/1656113/hibernate-many-to-many-ass-ation-with-the-same-entity)に遭遇しました。friendOfの別のコレクションが必要なようです。質問、本当に双方向の関係が必要ですか? (また、5つのテーブルを作成するのではなく、これを3つのテーブルに簡略化することもできます(joinColumnを使用) – HeavenAgain

0

Hibernateは、Userエンティティ用に1つのテーブルのみを生成し、User to User関係の相互参照テーブルを想定しています。別のテーブルを有することに回避策は、別の関係が

ユーザエンティティ

@OneToMany 
List<Follower> followers; 

フォロワーエンティティEAGERフェッチについては

@Entity 
class Follower 
... 
@ManyToOne 
User user; 

@Id 
@Generated 
int id; 

、あなたが実際のすべてをお勧めしますIE用の異なるエンティティのセットアップを持つかもしれませんLAZYになるものは、データベースがどのように設定されているかによって、それらの熱心な負荷はすべて非常に高価になる可能性があるためです。ユーザーがフォロワーをロードしたいときだけ、それらをフェッチしたいでしょう。別

0

からUser_IDをマッピングし、少なくとも2列を持つテーブルを作るためにUserFriends試してから、彼のすべてのFriends_IDsできるだけ早く基本的にALLデータをロードします。またEAGERUser_ID

への参照ですあなたはそれを初めて呼びます。すべてのユーザーとその友だちを読み込むことを意味します。友だちの読み込みにはLAZYが必要です。必要なときにのみ読み込まれます。

+0

これは私が考えていることですが、すべてのユーザー参照であるため、どのように私のケースでテーブルを分割するのですか? – HeavenAgain

関連する問題