4.2.3.2. Ассоциация Many-to-Many через связующую сущность
Отношения many-to-many всегда требуют создания связующей таблицы в базе данных, однако создание отдельной сущности для отражения этой таблицы является опциональным. Связующую сущность необходимо создать в том случае, если вы хотите хранить в связующей таблице некие дополнительные поля.
Продемонстрируем этот подход на примере сущностей Airport
и DutyFree
. В одном аэропорту может располагаться множество разных сетей магазинов беспошлинной торговли, и одна сеть duty-free может быть представлена во множестве разных аэропортов. Предположим, что кроме связи сущностей мы хотим хранить ещё и валюту, используемую в данном магазине в данном аэропорту:
-
Airport.java - сущность
Airport
содержит one-to-many коллекцию экземпляровAirportDutyFree
.В редакторе сущностей Studio установите следующие свойства для атрибута
dutyFreeShops
: Attribute type -COMPOSITION
, Cardinality -ONE_TO_MANY
.@Composition @OnDelete(DeletePolicy.CASCADE) @OneToMany(mappedBy = "airport") protected List<AirportDutyFree> dutyFreeShops;
-
DutyFree.java - сущность
DutyFree
также содержит one-to-many коллекцию экземпляровAirportDutyFree
.В редакторе сущностей Studio установите следующие свойства для атрибута
airports
: Attribute type -COMPOSITION
, Cardinality -ONE_TO_MANY
.@Composition @OnDelete(DeletePolicy.CASCADE) @OneToMany(mappedBy = "dutyFree") protected List<AirportDutyFree> airports;
-
AirportDutyFree.java - таким образом, связующая сущность
AirportDutyFree
содержит два ссылочных атрибута с отношением many-to-one:airport
иdutyFree
:@ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "AIRPORT_ID") protected Airport airport; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "DUTY_FREE_ID") protected DutyFree dutyFree;
-
views.xml - представление
airport-duty-free
экрана редактирования аэропорта содержит атрибут-коллекциюdutyFreeShops
(со ссылками наAirportDutyFree
), а в ней атрибутыdutyFree
иcurrency
.Представление
dutyFree-airport
следует той же логике: оно содержит атрибут-коллекциюairports
(со ссылками наAirportDutyFree
), а в ней атрибутыairport
иcurrency
. -
duty-free-edit.xml - XML-дескриптор экрана редактирования магазина duty-free определяет источник данных для экземпляра
DutyFree
и вложенный источник для его аэропортов. Кроме того, экран содержит таблицу, отображающую аэропорты, и действие, позволяющее выбирать аэропорт напрямую, минуя экран редактирования связующей сущностиAirportDutyFree
.
В результате редактирование экземпляра DutyFree
работает следующим образом:
В экране редактирования DutyFree
отображается таблица аэропортов и выпадающий список валют.
По нажатию Add airport открывается экран выбора Airport
, и пользователь может как выбрать аэропорт, так и открыть экран его редактирования. Когда экземпляр аэропорта выбран, создаётся новый экземпляр сущности AirportDutyFree
, которому проставляется валюта по умолчанию. Этот экземпляр связующей сущности не сохраняется в базу данных, а добавляется в источник данных airportsDs
экрана редактирования DutyFree
.
Когда пользователь нажимает OK в экране редактирования аэропорта, изменённый экземпляр аэропорта сохраняется и в базу данных, и в источник данных airportsDs
экрана редактирования DutyFree
, так как сущность Airport
является полностью независимой.
Пользователь может сохранять новые аэропорты или удалять их, и все изменения будут сохраняться в базу данных в отдельных транзакциях, а также в источник данных airportsDs
.
Когда пользователь нажимает OK в экране редактирования магазина, изменённый экземпляр DutyFree
вместе со всеми измененными экземплярами AirportDutyFree
отправляется на middleware в метод DataManager.commit() и сохраняется в базе данных в рамках одной транзакции.