0

我想設計某種用戶到用戶的關係,比如「用戶A關注用戶B」和「用戶A想成爲用戶B的朋友」。休眠@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; 

} 

我遇到了兩個問題:

  • Hibernate是爲了給我不能同時讀取多個袋問題
  • 我在網上查過,人們說要刪除FetchType.EAGER或將其改爲Set而不是List,但那導致我Field doe sn't有一個默認值

我有關係沒有正確定義的感覺,我也應該看到更多的表,因爲現在,我只看到用戶表,並且User_User表。


更新

下面創建3桌,朋友,追隨者,和請求者。與5個表相比,這是否有所優化?與Jmes先生的建議相比,這有什麼優勢嗎?

@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

首先,要實現您的功能,您應該使用@ManyToMany而不是@OneToMany。它應該看起來像這樣:

@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。但事實是,一個人可以追隨許多人,一個人可以追隨許多人。換句話說,A and B can also follow D

此外,你根本不應該使用cascadeType.ALL。該級聯策略意味着如果一個用戶刪除了他的賬戶,並刪除了數據庫中的相應條目,他的所有朋友等也將被刪除。

+0

'Hibernate:insert into User_User(requests_id,friendrequests_id)values(?,?) 2012-01-12 00:52:04,900 WARN [SqlExceptionHelper] SQL錯誤:1364,SQLState:HY000 2012-01-12 00:52 :04,901錯誤[SqlExceptionHelper]字段'following_id'沒有默認值' 這是我得到的問題。我認爲user_user表有5列,這是沒有必要的。而當我只需要更新請求或跟隨時,另一個沒有設置,這引發了這個問題。 – HeavenAgain 2012-01-12 05:55:15

+0

@ user1129335如果你的關係真的是雙向的,就像我提到的那樣,你沒有選擇。爲了解決你的問題,我用'@ JoinTable'註解更新了我的答案。這個註釋將幫助你爲你的關係創建5個不同的表格。 – 2012-01-12 06:31:54

+0

有兩件事我想問,你提到的'cascadeType.ALL'的效果聽起來像是一種期望的效果,因爲如果用戶刪除了他的賬戶,那麼我們並不真的想要一個鬼用戶?但那不是重點。我遇到了這個[post](http://stackoverflow.com/questions/1656113/hibernate-many-to-many-association-with-the-same-entity),好像我需要friendOf的另一個集合。問題是否真的有必要建立雙向關係? (而不是像你一樣創建5個表,這可以簡化爲三個表?使用joinColumn) – HeavenAgain 2012-01-12 06:42:16

0

Hibernate將只爲用戶實體生成一個表,並且我假設用戶到用戶關係的交叉引用表。解決方法具有不同的表可能具有不同的實體設置爲不同的關係,即

用戶實體

@OneToMany 
List<Follower> followers; 

跟隨實體

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

@Id 
@Generated 
int id; 

至於熱切取,你可能真的希望所有的那些懶惰,因爲根據你的數據庫設置的方式,所有這些急切的負載可能會相當昂貴。只有當用戶想要加載用戶追隨者時,我纔想要取回他們。

0

分開UserFriends嘗試使具有至少2列的表,該User_ID來映射所有他Friends_IDs其儘快基本上是User_ID

而且EAGER參考將加載ALL數據你第一次給它打電話。意味着它會加載所有的用戶和他們的朋友。加載朋友應該是LAZY,即只在需要時加載。

+0

這就是我的想法,但是,我怎麼在我的情況下分開表,因爲它是所有用戶引用。 – HeavenAgain 2012-01-12 05:46:43