Понимание двунаправленных отношений из документации Hibernate

1

Я просматриваю документацию Hibernate для двунаправленных отношений, в документе говорится, что:

Пример 7.21. Двунаправленная одна для многих со многими в одну сторону как владелец ассоциации

@Entity
public class Troop {
    @OneToMany(mappedBy="troop")
    public Set<Soldier> getSoldiers() {
    ...
}

@Entity
public class Soldier {
    @ManyToOne
    @JoinColumn(name="troop_fk")
    public Troop getTroop() {
    ...
}   

Отряд имеет двунаправленную связь со многими солдатами с солдатом. Вы не должны (не должны) определять какое-либо физическое сопоставление на стороне mappedBy.

Чтобы отобразить двунаправленную для многих, со стороны "один-ко-многим" в качестве стороны-владельца, вы должны удалить элемент mappedBy и установить много в один @JoinColumn как вставляемый и обновляемый на false. Это решение не оптимизировано и будет содержать дополнительные инструкции UPDATE.

Пример 7.22. Двунаправленная связь с одной до многих сторон как владелец

@Entity
public class Troop {
    @OneToMany
    @JoinColumn(name="troop_fk") //we need to duplicate the physical information
    public Set<Soldier> getSoldiers() {
    ...
}

@Entity
public class Soldier {
    @ManyToOne
    @JoinColumn(name="troop_fk", insertable=false, updatable=false)
    public Troop getTroop() {
    ...
}

Мне трудно понять это, поскольку я новичок в Hibernate.

1) Что это означает, когда документ говорит: You don't have to (must not) define any physical mapping in the mappedBy side.

2) @JoinColumn в 7.22 имеет такое же значение (troop_fk) для атрибута name. Можем ли мы указать разные значения? В чем преимущество и недостатки установки insertable=false, updatable=false здесь?

Может кто-нибудь объяснить?

Теги:
hibernate

1 ответ

3
Лучший ответ

Это двунаправленная ассоциация. Итак, если солдат уходит в отряд, в отряд входит солдат. Это всего лишь два способа сказать одно и то же.

В Soldier вы сообщаете, как ассоциация представлена в базе данных: используя столбец объединения с именем troop_fk:

@JoinColumn(name="troop_fk")
public Troop getTroop() {

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

@OneToMany(mappedBy="troop")
public Set<Soldier> getSoldiers() {

вы сообщаете Hibernate, что getSoldiers() является обратной стороной двунаправленной связи и что способ сопоставления этой ассоциации можно найти в Soldier.troop.

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

Этот способ - уродливый взлом, который AFAIK не поддерживается спецификацией JPA. Спецификация JPA предусматривает, что сторона владельца двунаправленной ассоциации OneToMany является большой стороной. Фактически он создает две однонаправленные ассоциации, сопоставленные одинаково, и сообщает Hibernate (используя insertable = false и updatable = false), чтобы игнорировать один из них при сохранении объекта. Он будет заполнять soldier.troop при чтении солдата из базы данных, но все, что вы введете в soldier.troop, будет игнорироваться при спасении солдата. Вы должны избегать этого способа, ИМХО.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню