Hibernate: Отображение отношений User-Friends в социальных сетях - PullRequest
3 голосов
/ 28 декабря 2008

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

Я пытаюсь смоделировать пользователя в социальной сети, используя 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 неправильно, потому что у меня нет четкого различия между другом и другом. Пока все хорошо, я получаю ошибку, но как я могу делать то, что я хочу?

Есть идеи? Я достиг конца моей мудрости.

Ответы [ 5 ]

1 голос
/ 29 декабря 2008

Фактом «многие ко многим» является то, что ему нужно немного больше конфигурации, потому что крайне важно, чтобы 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;
}

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

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

1 голос
/ 28 декабря 2008

Аннотация ManyToMany имеет параметр mappedBy. Я думаю, что-то вроде

@ManyToMany(mappedBy = "friends")

может работать. В любом случае см. документы .

Edit:

Кажется, что отношения между многими должны быть доступны с обеих сторон. В настоящее время ваш доступен только с одного конца. Возможно, вам следует добавить и другое отношение:

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

Если это не сработает, вы всегда можете ввести отдельный класс, представляющий отношение между двумя пользователями, и позволить каждому пользователю иметь коллекцию экземпляров этого класса.

0 голосов
/ 25 февраля 2009

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

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

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

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

from User as u left join fetch u.friends

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

0 голосов
/ 28 декабря 2008

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

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

0 голосов
/ 28 декабря 2008

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

...