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() и сохраняется в базе данных в рамках одной транзакции.