Hibernate @OneToMany 关系映射

发布于 2024-12-26 05:10:11 字数 1888 浏览 1 评论 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,但这导致我字段没有默认值

我感觉关系没有正确定义,而且我应该看到更多表,因为现在我只看到 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

番薯 2025-01-02 05:10:11

首先,要实现您的功能,您应该使用 @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;
}

对我来说,你们的关系看起来是双向的。如果您使用@O​​neToMany,则意味着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:

@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;
}

Your relationships looks like bidirectional ones to me. If you use @OneToMany, it means that C 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.

不奢求什么 2025-01-02 05:10:11

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

用户实体

@OneToMany
List<Follower> followers;

追随者实体

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

@Id
@Generated
int id;

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

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

@OneToMany
List<Follower> followers;

Follower Entity

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

@Id
@Generated
int id;

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.

深爱不及久伴 2025-01-02 05:10:11

UserFriends 分开,尝试制作一个至少包含 2 列的表格,将 User_ID 映射到他的所有 Friends_IDs > 基本上是对 User_ID 的引用,

此外,EAGER 将在您第一次调用它时加载全部数据。意味着它将加载所有用户及其朋友。加载好友应该是LAZY,即仅在需要时才加载。

Separate the User from Friends try to make a table with at least 2 columns that maps the User_ID to all his Friends_IDs which is basically a reference to User_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 be LAZY, i.e. only loaded when you need them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文