Search code examples
jpacomboboxone-to-manycuba-platform

LookupField with one-to-many relationship


I want to show in my document a one-to-many relationship- a simple drop-down list with values. For that, I trying to create and configure LookupField component by using Cuba platform.

I have two entities:

CardItem:

@NamePattern("The document in the following state: %s|cardState")
@Table(name = "TKB_CARD_ITEM")
@Entity(name = "tkb$CardItem")
public class CardItem extends StandardEntity {

    // skipped

CardType:

@NamePattern("CardType: %s, %s |cardTypeItem, cardTypeName")
@Table(name = "TKB_CARD_TYPE")
@Entity(name = "tkb$CardType")
public class CardType extends StandardEntity {

    @OneToMany(targetEntity=CardItem.class )
    private List<CardItem> cardItems;

    // skipped

In my card-item-edit.xml I have the following:

<dsContext>
    <datasource id="CardItemDs" class="com.company.tkb.entity.CardItem" view="_local"/>
    <collectionDatasource id="CardTypeDs" class="com.company.tkb.entity.CardType" view="_local">
        <query>select c from tkb$CardType c</query>
    </collectionDatasource>
</dsContext>
<layout>
    <lookupField datasource="CardItemDs" property="cardTypeName" optionsDatasource="CardTypeDs"/>

I filled the table TKB_CARD_TYPE with some values. Now I'm trying to get a drop-down list with values when I create CardItem, but the list is empty.

What could be the problem?

I would be very grateful for the information. Thanks to all.


Solution

  • What helped:

    In CardItemEdit class I added the following:

    public class CardItemEdit extends AbstractEditor<CardItem> {
        @Inject
        private Datasource<CardItem> cardItemDs;
    
        @Inject
        private Metadata metadata;
    
        @Override
        public void init(Map<String, Object> params) {
            CardItem cardItem = metadata.create(CardItem.class);
            cardItemDs.setItem(cardItem);
        }   
    }
    

    Then I changed the direction of the relationship: part of my CardItem entity:

    @NamePattern("The document in the following state: %s|cardState")
    @Table(name = "TKB_CARD_ITEM")
    @Entity(name = "tkb$CardItem")
    public class CardItem extends StandardEntity {
    
        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name = "CARD_TYPE_ID")
        protected CardType cardType;
    
        // skipped
    

    Part of my CardType entity:

    @NamePattern("Тип входящего документа: %s | cardTypeName")
    @Table(name = "TKB_CARD_TYPE")
    @Entity(name = "tkb$CardType")
    public class CardType extends StandardEntity {
    
        // skipped
    

    I defined the dsContext and lookupField by this way:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <window xmlns="http://schemas.haulmont.com/cuba/window.xsd"
            caption="msg://editCaption"
            class="com.tkbbank.client.web.item.CardItemEdit"
            datasource="cardItemDs"
            focusComponent="fieldGroup"
            messagesPack="com.tkbbank.client.web.item">
    
         <dsContext>
            <datasource id="cardItemDs" class="com.tkbbank.client.entity.CardItem" allowCommit="false"/>
                <collectionDatasource id="cardTypeDs" class="com.tkbbank.client.entity.CardType" view="_local">
                <query>
                    <![CDATA[select e from demo$CardType e]]>
                </query>
            </collectionDatasource>
        </dsContext>
    
    
        <dialogMode forceDialog="true" width="AUTO"/>
        <layout expand="windowActions" spacing="true">
            <fieldGroup id="fieldGroup" datasource="cardItemDs">
                <column width="500px">
                    <field id="cardCreationDate" editable="false"/>
                    <field id="cardType" caption="Тип документа">
                        <lookupField datasource="cardItemDs" property="cardType" optionsDatasource="cardTypeDs"/>
                    </field>
                    <field id="cardSubtype"/>
                    <field id="cardAutoFill"/>
                    <field id="cardOutcomeNumber"/>
                    <field id="cardDate"/>
                    <field id="cardOrganization"/>
                    <field id="cardDeliveryMethod"/>
                    <field id="cardAdditionalInformation"/>
                    <field id="registratorName"/>
                </column>
            </fieldGroup>
            <frame id="windowActions" screen="editWindowActions"/>
        </layout>
    </window>
    

    What I see now. My card:

    enter image description here

    Interface for populating CardType with data:

    enter image description here

    Interface viewing all the documents:

    enter image description here

    Now everything is ok.

    By side: very helpfull questions about "Can’t find getter for property" exception(this error is appeared also):