В чем разница между однонаправленными и двунаправленными ассоциациями?

В чем разница между однонаправленными и двунаправленными ассоциациями?

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

Это однонаправленная ассоциация

public class User {
    private int     id;
    private String  name;
    @ManyToOne
    @JoinColumn(
            name = "groupId")
    private Group   group;
}

public class Group {
    private int     id;
    private String  name;
}

Двунаправленная ассоциация

public class User {
    private int     id;
    private String  name;
    @ManyToOne
    @JoinColumn(
            name = "groupId")
    private Group   group;
}
public class Group {
    private int         id;
    private String      name;
    @OneToMany(mappedBy="group")
    private List<User>  users;
}

Разница заключается в том, содержит ли группа ссылку пользователя.

Так что, интересно, это только разница? который рекомендуется?

Ответ 1

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

Обратите внимание, что навигационный доступ не всегда хорош, особенно для отношений "один-очень-много" и "многие-очень-многие". Представьте себе Group, который содержит тысячи User s:

  • Как бы вы к ним обращались? С таким количеством User s вам обычно нужно применить некоторую фильтрацию и/или разбиение на страницы, так что вам все равно нужно выполнить запрос (если вы не используете фильтрацию коллекции, который выглядит как хак для меня). Некоторые разработчики могут применять фильтрацию в памяти в таких случаях, что явно не подходит для производительности. Обратите внимание: наличие таких отношений может побудить таких разработчиков использовать его без учета последствий для производительности.

  • Как добавить новый User в Group? К счастью, Hibernate смотрит на собственную сторону отношений при его сохранении, поэтому вы можете установить только User.group. Однако, если вы хотите, чтобы объекты в памяти были совместимы, вам также нужно добавить User в Group.users. Но это сделало бы Hibernate для извлечения всех элементов Group.users из базы данных!

Итак, я не могу согласиться с рекомендацией Best Practices. Вам необходимо тщательно разработать двунаправленные отношения, учитывая варианты использования (вам нужен навигационный доступ в обоих направлениях?) И возможные последствия для производительности.

См. также:

Ответ 2

В терминах кодирования двунаправленная взаимосвязь более сложна для реализации, поскольку приложение отвечает за синхронизацию обеих сторон в соответствии со спецификацией JPA 5 (на стр. 42). К сожалению, приведенный в спецификации пример не дает более подробной информации, поэтому он не дает представления об уровне сложности.

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

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

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

Ответ 3

Я не уверен на 100%, это единственная разница, но это основное различие. Также рекомендуется иметь двунаправленные ассоциации по документам Hibernate:

http://docs.jboss.org/hibernate/core/3.3/reference/en/html/best-practices.html

В частности:

Предпочитают двунаправленные ассоциации:      Однонаправленные ассоциации сложнее запросить. В большой приложения, почти все ассоциации должна быть судоходной в обоих направлениях в запросах.

У меня лично есть небольшая проблема с этой общей рекомендацией - мне кажется, что бывают случаи, когда у ребенка нет какой-либо практической причины знать о своем родителе (например, почему элемент заказа должен знать о порядок связан с?), но я вижу в нем значение разумной части времени. И так как двунаправленность на самом деле ничего не болит, я не считаю это слишком неприемлемым для соблюдения.