Hibernate @OneToMany关系映射

时间:2012-01-12 04:49:58

标签: java hibernate one-to-many hibernate-mapping hibernate-onetomany

我正在设计某种用户关系,例如“用户A跟随用户B”和“用户A想成为用户B的朋友”。

我有一个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,但这导致我字段没有默认值

我感觉关系没有正确定义,而且我应该看到更多的表,因为现在,我只看到User表和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;

3 个答案:

答案 0 :(得分: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。该级联策略意味着如果一个用户删除了他的帐户并删除了数据库中的相应条目,他的所有朋友等也将被删除。

答案 1 :(得分:0)

Hibernate只为User实体生成一个表,我假设用户与用户关系的交叉引用表。使用不同表格的解决方法可能是为不同的关系设置了不同的实体,即

用户实体

@OneToMany
List<Follower> followers;

追随者实体

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

@Id
@Generated
int id;

对于EAGER提取,您实际上可能希望所有这些都是LAZY,因为根据数据库的设置方式,所有这些急切的负载都可能非常昂贵。只有当用户想要加载用户关注者时,我才想要获取它们。

答案 2 :(得分:0)

UserFriends分开,尝试创建一个至少包含2列的表格,将User_ID映射到所有Friends_IDs,这基本上是User_ID的引用1}}

第一次调用时,EAGER也会加载所有数据。意味着它将加载所有用户及其朋友。加载好友应该是LAZY,即只在您需要时加载。