Впадать в спящий режим:Отображение отношений между пользователями и Друзьями в социальных сетях
-
29-08-2019 - |
Вопрос
Прошло довольно много времени, пока я пытаюсь разобраться в этой проблеме, и, погуглив, многие люди сталкиваются с подобными проблемами.
Я пытаюсь смоделировать пользователя в социальной сети, используя 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, не имея четкого различия между friend и befriended .Пока все хорошо, я получаю сообщение об ошибке, но как я могу делать то, что я хочу?
Есть какие-нибудь идеи?Я достиг предела своей мудрости.
Решение
Факт о многих ко многим заключается в том, что ему требуется немного больше настроек, потому что обязательно, чтобы 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;
}
Надеюсь, это сработает =)
Редактировать:Кроме того, будьте очень осторожны с типами выборки...вы можете войти в неконтролируемый цикл выборки пользователя и получить всю базу данных.
Другие советы
В ManyToMany
аннотация имеет параметр mappedBy.Я предполагаю, что что-то вроде
@ManyToMany(mappedBy = "friends")
может сработать.В любом случае, смотрите Документы.
Редактировать:
Кажется, что отношения "многие ко многим" должны быть доступны с обоих концов.В настоящее время ваш доступен только с одного конца.Может быть, вам следует добавить и другое отношение:
@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;
}
Если это не сработает, вы всегда можете ввести отдельный класс, представляющий связь между двумя пользователями, и позволить каждому пользователю иметь коллекцию экземпляров этого класса.
Хороший довод, и на самом деле я это пробовал.Проблема в том, что затем я получаю жалобу на то, что атрибут mappedBy установлен на обеих сторонах отношения, что верно, но недопустимо.Мне было интересно, будет ли простой @ManyToMany
с помощью какого-нибудь умного пользовательского запроса поиск друзей мог бы стать решением:В ManyToMany
сгенерировал бы таблицу объединения с user_id
и friend_id,
но запрос будет соответствовать любому из полей, возвращая всех пользователей, где это соответствует либо friend_id
или тот user_id
то есть.Есть какие-нибудь идеи?
Это, конечно, было бы хорошим решением, но я еще не полностью продан.По сути, чтобы привлечь друзей, мне пришлось бы объединить две коллекции, что довольно неудовлетворительно.
Неужели нет абсолютно никакого способа создать идемпотентное, рефлексивное отношение в hibernate?
Сегодня у меня тоже была такая же проблема.
@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
Это инициализирует список друзей для этого объекта.Однако имейте в виду, что он не инициализирует никаких друзей из этих друзей.На самом деле это хорошо.