4.3.4. Композиция One-to-One в одном редакторе

Сущности, связанные композицией с типом один-к-одному, часто бывает удобно создавать в одном общем экране редактирования. Рассмотрим, как можно реализовать такой экран, на примере отношений сущностей Customer и CustomerDetails.

  • customer-edit.xml содержит основной источник данных customerDs и вложенный в него detailsDs:

    <dsContext>
        <datasource id="customerDs"
                    class="sample.entity.Customer"
                    view="customer-view">
            <datasource id="detailsDs"
                        property="details"/>
        </datasource>
    </dsContext>

    Поля для редактирования обеих сущностей сгруппированы в один компонент fieldGroup, где отдельные поля привязаны к вложенному источнику данных:

    <fieldGroup id="customerGroup"
                datasource="customerDs">
        <column width="200px">
            <field property="name"/>
            <field property="email"/>
            <field datasource="detailsDs"
                   property="address"
                   rows="3"/>
            <field datasource="detailsDs"
                   property="note"
                   rows="3"/>
        </column>
    </fieldGroup>
  • В контроллере экрана CustomerEdit мы переопределяем метод initNewItem(). В нём создаём новый экземпляр CustomerDetails и связываем его с только что созданным экземпляром Customer:

    @Inject
    private Metadata metadata;
    
    @Override
    protected void initNewItem(Customer customer) {
        customer.setDetails(metadata.create(CustomerDetails.class));
    }

    Напоследок обработаем ситуацию, когда пользователь нажимает Create, а затем закрывает редактор экрана без каких-либо изменений в полях покупателя. По умолчанию, пользователю будет предложено сохранить или отменить изменения, так как detailsDs уже содержит пустой экземпляр CustomerDetails, а значит, метод isModified() вернёт true. Чтобы предотвратить появление такого диалога для пустых сущностей, заставим метод isModified() принимать во внимание только изменения в главном источнике данных экрана:

    @Override
    public boolean isModified() {
        return customerDs.isModified();
    }

Теперь обе сущности можно создавать и редактировать в одном экране.