Hibernate: сопоставление отношений пользователей и друзей в социальных сетях

Уже довольно давно я пытаюсь разобраться в этой проблеме, и, погуглив, у многих людей есть похожие проблемы.

Я пытаюсь смоделировать пользователя в социальной сети, используя 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
}

Теперь проблема в том, что он говорит мне, что я неправильно использую ManyToMany, поскольку у меня нет четкого различия между другом и другом. Пока все хорошо, я получаю сообщение об ошибке, но как я могу сделать то, что хочу?

Есть идеи? Я достиг предела своей мудрости.


person cdecker    schedule 28.12.2008    source источник


Ответы (5)


Дело в том, что Many to Many требует немного большей настройки, потому что 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;
}

Надеюсь, это работает =)

РЕДАКТИРОВАТЬ: Кроме того, будьте очень осторожны с типами выборки... вы можете ввести пользовательскую выборку неконтролируемого цикла и получить всю БД.

person Juan Manuel    schedule 29.12.2008
comment
Могу ли я сделать только один список с друзьями, где будут друзья и друзья? Какой смысл иметь List в классе? - person dikkini; 03.07.2014


Хороший вопрос, и на самом деле я пробовал это. Проблема в том, что затем я получаю жалобу на то, что атрибут mappedBy установлен на обеих сторонах отношения, что верно, но недействительно. Мне было интересно, может ли простой @ManyToMany с каким-нибудь умным пользовательским запросом для получения друзей быть решением: ManyToMany создаст таблицу соединений с user_id и friend_id,, но запрос будет соответствовать любому из полей, возвращая всех пользователей, где это соответствует либо friend_id или user_id то есть. Любые идеи?

person cdecker    schedule 28.12.2008

Это, конечно, было бы хорошим решением, но я еще не полностью продался. По сути, чтобы получить друзей, мне пришлось бы объединить две коллекции, что совершенно неудовлетворительно.

Нет ли абсолютно никакого способа создать идемпотентное рефлексивное отношение в спящем режиме?

person cdecker    schedule 28.12.2008

У меня сегодня тоже была такая же проблема.

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

Должно быть хорошо, я использовал аналогичную структуру. Однако я получил ленивую загрузку исключений, и при установке fetchType в EAGER я получил жалобы на рекурсивную инициализацию мешков.

Как я исправил свою проблему: в запросе, который вы используете для получения «пользователя», сделайте что-то вроде:

from User as u left join fetch u.friends

Это инициализирует список друзей для этой сущности. Имейте в виду, однако, что он не инициализирует друзей из этих друзей. На самом деле это хорошо.

person Matthias van der Vlies    schedule 25.02.2009