5.8.4.1. Реализация композиции
Рассмотрим реализацию композиции на примере сущностей Airport и Terminal:
-
Сущность
Terminalсодержит обязательную ссылку наAirport:@Entity(name = "sample$Terminal") @Table(name = "SAMPLE_TERMINAL") public class Terminal extends StandardEntity { ... @ManyToOne(optional = false, fetch = FetchType.LAZY) @JoinColumn(name = "AIRPORT_ID") private Airport airport; public Airport getAirport() { return airport; } public void setAirport(Airport airport) { this.airport = airport; } } -
Сущность
Airportсодержит one-to-many коллекцию терминалов. Соответствующее поле помечается аннотацией @Composition для огранизации композиции и @OnDelete для каскадного мягкого удаления:@Entity(name = "sample$Airport") @Table(name = "SAMPLE_AIRPORT") public class Airport extends StandardEntity { ... @OneToMany(fetch = FetchType.LAZY, mappedBy = "airport") @OnDelete(DeletePolicy.CASCADE) @Composition protected List<Terminal> terminals; public List<Terminal> getTerminals() { return terminals; } public void setTerminals(List<Terminal> terminals) { this.terminals = terminals; } } -
Представление, используемое в экране редактирования аэропорта, должно содержать атрибут-коллецию
terminals:<view entity="sample$Airport" name="airport-edit" extends="_local"> <property name="terminals" view="_local"/> </view>Для сущности
Terminalздесь выбрано представление_local, хотя она содержит ссылочный атрибутairport- ссылку на аэропорт. Дело в том, что атрибутairportустанавливается только при создании нового экземпляраTerminal, и не меняется в дальнейшем, поэтому загружать его не обязательно. -
В XML-дескрипторе экрана редактирования аэропорта определяем источники данных для экземпляра
Airportи коллекции его терминалов:<dsContext> <datasource id="airportDs" class="com.haulmont.sample.entity.Airport" view="airport-edit"> <collectionDatasource id="terminalsDs" property="terminals"/> </datasource> </dsContext> -
В XML-дескрипторе экрана редактирования аэропорта определяем таблицу, отображающую терминалы, и стандартные действия для нее:
<table id="terminalsTable"> <actions> <action id="create"/> <action id="edit"/> <action id="remove"/> </actions> <buttonsPanel> <button action="terminalsTable.create"/> <button action="terminalsTable.edit"/> <button action="terminalsTable.remove"/> </buttonsPanel> <columns> <column id="code"/> <column id="name"/> <column id="address"/> </columns> <rows datasource="terminalsDs"/> </table> -
В экране редактирования терминала достаточно определить стандартные элементы:
datasourceдля экземпляраTerminalи визуальные компоненты, связанные с этимdatasource, для редактирования атрибутов терминала.
В результате редактирование экземпляра аэропорта работает следующим образом:
-
В экране редактирования аэропорта отображается таблица терминалов.
-
Пользователь может выбрать терминал и открыть экран его редактирования. При нажатии OK в экране редактирования терминала измененный экземпляр терминала сохраняется не в базу данных, а в источник данных
terminalsDsэкрана редактирования аэропорта. -
Пользователь может создавать новые или удалять терминалы - все изменения сохраняются в источнике данных
terminalsDs. -
Пользователь нажимает OK в экране редактирования аэропорта, и измененный
Airportвместе со всеми измененными экземплярамиTerminalотправляется на Middleware в метод DataManager.commit() и сохраняется в базе данных в рамках одной транзакции.