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 表。
Update
以下创建 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;
I am trying to design some kind of user to user relationship, such as "user A follows user B" and "User A wants to be User B's friend".
I have a User class, and the way it is designed looks like this:
@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;
}
I am running into two problems:
- Hibernate is giving me cannot simultaneously fetch multiple bags problem
- I have looked up online, people said to remove FetchType.EAGER or change it to Set instead of List, but that resulted me Field doesn't have a default value
I have a feeling that the relationship is not defined properly, and also I should be seeing more tables, because right now, I only see User table, and User_User table.
Update
The following creates 3 table, friends, followers, and requesters. Is this somewhat optimized compared to 5 tables? And are there any advantage to this in comparison with what Mr.J4mes suggested?
@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;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
首先,要实现您的功能,您应该使用
@ManyToMany
而不是@OneToMany
。它应该是这样的:对我来说,你们的关系看起来是双向的。如果您使用@OneToMany,则意味着
C有2个关注者A和B
=A和B仅关注C
。然而事实是,一个人可以关注很多人,一个人也可以被很多人关注。换句话说,A和B也可以跟随D
。此外,您根本不应该使用
cascadeType.ALL
。这种级联策略意味着,如果一个用户删除了他的帐户,并且您删除了数据库中的相应条目,那么他的所有朋友等也将被删除。First of all, to implement your feature, you should use
@ManyToMany
instead of@OneToMany
. It should look like this:Your relationships looks like bidirectional ones to me. If you use
@OneToMany
, it means thatC has 2 followers A and B
=A and B only follows C
. However, the fact is that one person can follows many people and one person can be followed by many people. In other words,A and B can also follow D
.Besides, you shouldn't use
cascadeType.ALL
at all. That cascade policy means that if one user deletes his account and you delete the corresponding entry in the database, all of his friends, etc. will also be deleted.Hibernate 只会为用户实体生成一张表,并且我假设用户与用户关系有一个交叉引用表。拥有不同表的解决方法可能是为不同的关系设置不同的实体,即
用户实体
追随者实体
至于急切获取,您实际上可能希望所有这些都是惰性的,因为这取决于数据库的设置方式,所有这些急切的负载可能会非常昂贵。只有当用户想要加载用户关注者时,我才会想要获取它们。
Hibernate will only generate one table for the User entity, and I'm assuming a cross reference table for the User to User relationship. Workaround to having different tables might be having different entities setup for the different relationships i.e.
User Entity
Follower Entity
As for the EAGER fetching, you might actually want all of those to be LAZY, due to the fact that depending on how your database is set up, all of those eager loads could be quite expensive. Only when the user wants to load the users followers, would I want to fetch them.
将
User
与Friends
分开,尝试制作一个至少包含 2 列的表格,将User_ID
映射到他的所有Friends_IDs
> 基本上是对User_ID
的引用,此外,
EAGER
将在您第一次调用它时加载全部数据。意味着它将加载所有用户及其朋友。加载好友应该是LAZY
,即仅在需要时才加载。Separate the
User
fromFriends
try to make a table with at least 2 columns that maps theUser_ID
to all hisFriends_IDs
which is basically a reference toUser_ID
Also
EAGER
will load ALL the data as soon as you call it the first time. Means it will load all the Users and their Friends. Loading friends should beLAZY
, i.e. only loaded when you need them.