0

我正在尝试设计某种用户与用户的关系,例如“用户 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,但这导致我的 Field 没有默认值

我感觉关系没有正确定义,而且我应该看到更多的表,因为现在我只看到 User 表和 User_User 表。


更新

下面创建 3 个表、朋友、关注者和请求者。与 5 个表相比,这是否有所优化?与 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;
4

3 回答 3

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

于 2012-01-12T05:37:45.003 回答
0

Hibernate 只会为 User 实体生成一个表,我假设 User to User 关系的交叉引用表。拥有不同表的解决方法可能是为不同的关系设置不同的实体,即

用户实体

@OneToMany
List<Follower> followers;

追随者实体

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

@Id
@Generated
int id;

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

于 2012-01-12T05:20:04.667 回答
0

UserfromFriends尝试制作一个至少有 2 列的表,将其映射User_ID到他的所有Friends_IDs内容,这基本上是对User_ID

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

于 2012-01-12T05:31:35.403 回答