Hibernate:在社交网络中映射用户 - 朋友关系

时间:2022-11-30 16:57:14

It's quite some time that I'm trying to figure out this problem and from googling around many people have similar problems.

现在已经有一段时间了,我正试图找出这个问题,并且从谷歌上搜索许多人都有类似的问题。

I'm trying to model a User in a Social Network, using Hibernate, and what is more basic to a social network than to map a friendship relation? Every user in the system should have a list of it's friends and I thought that this might be an incredibly easy task (just use a ManyToMany relation, right?). So I went on to try the following:

我正在尝试使用Hibernate为社交网络中的用户建模,而对于社交网络来说,什么比映射友谊关系更基本?系统中的每个用户都应该有一个朋友列表,我认为这可能是一个非常容易的任务(只需使用ManyToMany关系,对吧?)。所以我继续尝试以下方法:

@Entity
@Table(name="users")
public class User {
   @Id
   @GeneratedValue(strategy=GenerationType.AUTO)
   @Column(name="userid")
   protected Long id = null;
   @ManyToMany
   protected List<User> friends = null
}

The problem now is that it tells me I use ManyToMany wrongly by having no clear distinction between friend and befriended. So far so good, I get the error, but how can I do what I want?

现在的问题是它告诉我,由于朋友和朋友之间没有明确的区别,我错误地使用了ManyToMany。到目前为止这么好,我得到了错误,但我怎么能做我想要的呢?

Any idea? I've reached the end of my wisdom.

任何的想法?我的智慧已经结束了。

5 个解决方案

#1


The fact about Many to Many is that it needs a little more configuration, because its imperative that Hibernate generates a relation table. Try this:

关于多对多的事实是它需要更多的配置,因为Hibernate必须生成关系表。试试这个:


@Entity
@Table(name="users")
public class User {
   @Id
   @GeneratedValue(strategy=GenerationType.AUTO)
   @Column(name="userid")
   protected Long id = null;
   @ManyToMany
   @JoinTable(name = "user_friends", 
       joinColumns = @JoinColumn(name = "user_id"), 
       inverseJoinColumns = @JoinColumn(name = "friend_id"))
   protected List friends = null;
   @ManyToMany(mappedBy = "friends")
   protected List befriended = null;
}

Hope it works =)

希望它有效=)

EDIT: Also, be very careful with fetch types... you can enter an user fetching out-of-control loop and get all the DB.

编辑:另外,要非常小心获取类型...您可以输入用户获取失控循环并获取所有数据库。

#2


The ManyToMany annotation has a mappedBy parameter. I guess something like

ManyToMany注释具有mappedBy参数。我觉得类似的东西

@ManyToMany(mappedBy = "friends")

might work. In any case, see the docs.

可能有用。无论如何,请参阅文档。

Edit:

It seems as if a many to many relationship needs to be accessible from both ends. Currently yours is only accessible from one end. Maybe you should add the other relation as well:

似乎需要从两端访问多对多关系。目前只能从一端访问您的。也许你应该添加其他关系:

@Entity
@Table(name="users")
public class User {
   @Id
   @GeneratedValue(strategy=GenerationType.AUTO)
   @Column(name="userid")
   protected Long id = null;
   @ManyToMany
   protected List<User> friends = null;
   @ManyToMany(mappedBy = "friends")
   protected List<User> befriended = null;
}

If that doesn't work you can always introduce a separate class representing the relation between two users, and let every user have a collection of instances of this class.

如果这不起作用,您总是可以引入一个表示两个用户之间关系的单独类,并让每个用户都拥有该类的实例集合。

#3


Good point, and in fact I tried that. Problem is that I then get a complaint about the mappedBy attribute being set on both sides of the relationship, which is true, but invalid. I was wondering wether a simple @ManyToMany with some clever custom query to fetch the friends might be a solution: The ManyToMany would generate a join table with user_id and friend_id, but the query would match either of the fields, returning all users where that match either the friend_id or the user_id that is. Any ideas?

好点,事实上我试过了。问题是我接到关于在关系两侧设置的mappedBy属性的投诉,这是真的,但是无效。我想知道一个简单的@ManyToMany有一些聪明的自定义查询来获取朋友可能是一个解决方案:ManyToMany将生成一个带有user_id和friend_id的连接表,但查询将匹配任一字段,返回匹配的所有用户无论是friend_id还是user_id。有任何想法吗?

#4


That of course would be a good fix, yet I'm not yet completely sold. Basically to get the friends I'd have to merge the two collections, which is quite unsatisfactory.

那当然是一个很好的解决方案,但我还没有完全卖掉。基本上,为了得到朋友,我必须合并两个集合,这是非常不满意的。

Is there absolutely no way to create an idempotent, reflexive relation in hibernate?

绝对没有办法在休眠中创建一个幂等的,反身的关系吗?

#5


I had the same problem today as well.

我今天也有同样的问题。

@Entity
@Table(name="users")
public class User {
   @Id
   @GeneratedValue(strategy=GenerationType.AUTO)
   @Column(name="userid")
   protected Long id = null;
   @ManyToMany
   protected List<User> friends = null
}

Should be ok, I used a similar structure. However I got lazy loading exceptions and when setting the fetchType to EAGER, I got complaints about recursive initialisation of bags.

应该没问题,我使用了类似的结构。但是我得到了延迟加载异常,当将fetchType设置为EAGER时,我得到了关于行李递归初始化的抱怨。

How I fixed my problem: In the query you use to fetch the 'user', do something like:

我如何解决我的问题:在用于获取“用户”的查询中,执行以下操作:

from User as u left join fetch u.friends

This will initialise the list of friends for that entity. Be warned though that it doesn't initialise any friends from those friends. That is a good thing actually.

这将初始化该实体的朋友列表。请注意,它不会初始化这些朋友的任何朋友。实际上这是一件好事。

#1


The fact about Many to Many is that it needs a little more configuration, because its imperative that Hibernate generates a relation table. Try this:

关于多对多的事实是它需要更多的配置,因为Hibernate必须生成关系表。试试这个:


@Entity
@Table(name="users")
public class User {
   @Id
   @GeneratedValue(strategy=GenerationType.AUTO)
   @Column(name="userid")
   protected Long id = null;
   @ManyToMany
   @JoinTable(name = "user_friends", 
       joinColumns = @JoinColumn(name = "user_id"), 
       inverseJoinColumns = @JoinColumn(name = "friend_id"))
   protected List friends = null;
   @ManyToMany(mappedBy = "friends")
   protected List befriended = null;
}

Hope it works =)

希望它有效=)

EDIT: Also, be very careful with fetch types... you can enter an user fetching out-of-control loop and get all the DB.

编辑:另外,要非常小心获取类型...您可以输入用户获取失控循环并获取所有数据库。

#2


The ManyToMany annotation has a mappedBy parameter. I guess something like

ManyToMany注释具有mappedBy参数。我觉得类似的东西

@ManyToMany(mappedBy = "friends")

might work. In any case, see the docs.

可能有用。无论如何,请参阅文档。

Edit:

It seems as if a many to many relationship needs to be accessible from both ends. Currently yours is only accessible from one end. Maybe you should add the other relation as well:

似乎需要从两端访问多对多关系。目前只能从一端访问您的。也许你应该添加其他关系:

@Entity
@Table(name="users")
public class User {
   @Id
   @GeneratedValue(strategy=GenerationType.AUTO)
   @Column(name="userid")
   protected Long id = null;
   @ManyToMany
   protected List<User> friends = null;
   @ManyToMany(mappedBy = "friends")
   protected List<User> befriended = null;
}

If that doesn't work you can always introduce a separate class representing the relation between two users, and let every user have a collection of instances of this class.

如果这不起作用,您总是可以引入一个表示两个用户之间关系的单独类,并让每个用户都拥有该类的实例集合。

#3


Good point, and in fact I tried that. Problem is that I then get a complaint about the mappedBy attribute being set on both sides of the relationship, which is true, but invalid. I was wondering wether a simple @ManyToMany with some clever custom query to fetch the friends might be a solution: The ManyToMany would generate a join table with user_id and friend_id, but the query would match either of the fields, returning all users where that match either the friend_id or the user_id that is. Any ideas?

好点,事实上我试过了。问题是我接到关于在关系两侧设置的mappedBy属性的投诉,这是真的,但是无效。我想知道一个简单的@ManyToMany有一些聪明的自定义查询来获取朋友可能是一个解决方案:ManyToMany将生成一个带有user_id和friend_id的连接表,但查询将匹配任一字段,返回匹配的所有用户无论是friend_id还是user_id。有任何想法吗?

#4


That of course would be a good fix, yet I'm not yet completely sold. Basically to get the friends I'd have to merge the two collections, which is quite unsatisfactory.

那当然是一个很好的解决方案,但我还没有完全卖掉。基本上,为了得到朋友,我必须合并两个集合,这是非常不满意的。

Is there absolutely no way to create an idempotent, reflexive relation in hibernate?

绝对没有办法在休眠中创建一个幂等的,反身的关系吗?

#5


I had the same problem today as well.

我今天也有同样的问题。

@Entity
@Table(name="users")
public class User {
   @Id
   @GeneratedValue(strategy=GenerationType.AUTO)
   @Column(name="userid")
   protected Long id = null;
   @ManyToMany
   protected List<User> friends = null
}

Should be ok, I used a similar structure. However I got lazy loading exceptions and when setting the fetchType to EAGER, I got complaints about recursive initialisation of bags.

应该没问题,我使用了类似的结构。但是我得到了延迟加载异常,当将fetchType设置为EAGER时,我得到了关于行李递归初始化的抱怨。

How I fixed my problem: In the query you use to fetch the 'user', do something like:

我如何解决我的问题:在用于获取“用户”的查询中,执行以下操作:

from User as u left join fetch u.friends

This will initialise the list of friends for that entity. Be warned though that it doesn't initialise any friends from those friends. That is a good thing actually.

这将初始化该实体的朋友列表。请注意,它不会初始化这些朋友的任何朋友。实际上这是一件好事。