Generic UI Filtri entità con attribute type COMPOSITION

Ciao a tutti,

vi espongo il mio problema:

ho un entità Person che ha una relazione n:m con l’entità CompanyRelations. Per mappare questa relazione ho utilizzato una tipologia COMPOSITION

  @Composition
    @OneToMany(mappedBy = "person")
    protected List<CompanyRelation> companyRelations;

Nello screen di browse ho definito i filtri in questo modo:

 <filter id="filter"
                    responsive="true"
                    applyTo="personsTable"
                    dataLoader="personsDl" width="100%" css="float:left;">
     <properties include=".*"/>
                <property name="companyRelations.company"/>
                <property name="companyRelations.startDate" caption="msg://company.startDate"/>
                <property name="companyRelations.endDate" caption="msg://company.endDate"/>
    </properties>
<filter>

Quando cerco di utilizzare il filtro company ottengo la seguente eccezione:

JPQLException: 
Exception Description: Problem compiling [select e from hfc_Person e where e.companyRelations.company.id = :filter_companyRelations_company00782 order by e.lastName desc, e.id desc]. 
[33, 62] The state field path 'e.companyRelations.company.id' cannot be resolved to a valid type.

Da notare che tutte le operazioni di inserimento, modifica e cancellazione funzionano correttamente.

Qualcuno di voi si è già scontrato con questo problema?

Grazie a tutti

Ciao @mnemonik83
purtroppo è un problema comune quando si iniziano ad usare gli ORM, e in particolare JPA con JPQL.
Le relazioni X a MOLTI sono problematiche, perché non esiste un corrispondente nei DB relazionali, e di conseguenza in SQL.
Ricorda che tutto ciò che fai, usando filtri o automatismi di CUBA, si traduce in JPQL prima, e in ultimo in SQL sul tuo DB di destinazione.

Pertanto devi sempre porti la domanda: quello che sto cercando di fare si può tradurre in SQL, o no?
La risposta in merito a companyRelations.company purtroppo è un grosso no :wink:

In particolare non puoi navigare (sia in JPQL che in SQL) oltre una relazione “a molti”, cioè tu partendo da Person puoi arrivare solo a companyRelations, ma non puoi dire "ok ma eseguimi una proiezione in modo da darmi company di ciascuna companyRelations". Quella è una cosa che puoi fare solo da codice Java, con stream() ad esempio o un semplice ciclo…

Se vuoi applicare filtri (where in JPQL) devi sempre partire dal lato one della relazione, cioè l’entità (tabella) che contiene la foreign key (esattamente come avviene in SQL, l’ORM nasconde il DB ma non lo puo snaturare).
Per questo motivo ad esempio le relazioni many to many offerte dagli ORM come JPA sono da evitare come la peste la maggior parte dei casi. Le puoi utilizzare per casi molto semplici, ma se pensi di dover fare anche solo una where o una join più complessa sulla relazione, ti toccherà smontarla in due many to one con una entità di correlazione.

Paolo

Ciao Paolo,

tutto chiaro. Aggiungo però che il parser di cuba potrebbe essere migliorato perché tecnicamente è fattibile trasformando la

select e from hfc_Person e where e.companyRelations.company.id = :filter_companyRelations_company00782

in

select e from hfc_Person e join hfc_CompanyRelation r on r.person = e where r.company.id = :filter_companyRelations_company00782

quindi come dici tu partendo dalla parte one della relazione.

Detto ciò ho trovato due strade alternative che mi vengono in aiuto:

  1. La prima è sfruttando i filtri custom:

Schermata 2020-12-04 alle 22.30.12

  1. La seconda è creando un nuovo criterio a runtime:

Schermata 2020-12-04 alle 22.27.42

Grazie per il supporto e buon lavoro

1 Mi Piace

Ciao
si tutto corretto, se giri la relazione il filtro è creabile, e le soluzioni che hai postato sono entrambe valide.

Il filtro di CUBA genera le query partendo sempre dalla query della collection a cui è collegato, ed è già forse troppo complesso per un utilizzo da parte di utenti avanzati ma non dev. Non credo che verrà ulteriormente esteso, anzi ho sentito proposte per semplificarlo ulteriormente…

Cmq per un dev non è così difficile creare estensioni custom, come hai giustamente fatto tu.

Ciao,
P.