Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Wie füge ich eine Where-Klausel zu einer Hibernate @OneToMany expliziten Join-Tabellenentität hinzu?

Ich habe die SQL-Protokollierung aktiviert und die Abfrageausgabe untersucht. Für den obigen Fall war es dies:

/* load one-to-many com.prepaytec.pacasso.common.model.Card.purchaseProductGroups */
select
    * /* the actual field list has been omitted for brevity */
from
    pacasso.purchaseprodgrp_card purchasepr0_
inner join
    pacasso.purchase_product_group purchasepr1_
        on purchasepr0_.ppg_id=purchasepr1_.ppg_id
where
    (
        exists (
            select
                *
            from
                purchase_product_group ppg
            where
                ppg.ppg_id = purchasepr0_.ppg_id
                AND ppg.ppg_status <> 'D'
        )
    )
    and purchasepr0_.crd_id=?

Der notwendige Join ist also bereits enthalten und sieht aus wie alles, was benötigt würde, ist dies:

@Where(clause = "ppg_status <> 'D'")

Es stellt sich jedoch heraus, dass dies nicht der Fall ist funktionieren, da Hibernate den falschen Tabellenaliasnamen voranstellt:

where
    (
        purchasepr0_.ppg_status <> 'D'
    )
    and purchasepr0_.crd_id=?

Sobald einer Tabelle ein Alias ​​zugewiesen wurde, ist es leider nicht möglich, den ursprünglichen Tabellennamen zu verwenden - also purchase_product_group.ppg_status <> 'D' würde nicht funktionieren. Und mir ist keine Möglichkeit bekannt, den von Hibernate verwendeten Aliasnamen programmgesteuert zu bestimmen - daher scheint die Wahl derzeit entweder darin zu bestehen, den von Hibernate verwendeten Aliasnamen fest zu codieren (dh purchasepr1_.ppg_status <> 'D' ) oder um den exists zu verwenden in der Frage beschriebene Methode.

AKTUALISIERUNG: Bei weiteren Nachforschungen stellt sich heraus, dass die Hardcodierung der Aliasnamen nicht immer praktikabel ist. Hier ist eine Kriterienabfrage, bei der dies nicht funktionieren würde:

/* criteria query */
select
    * /* the actual field list has been omitted for brevity */
from
    pacasso.merchant_acquirer this_ 
left outer join
    pacasso.purchaseprod_merchant_acquirer purchasepr2_ 
        on this_.mac_id=purchasepr2_.mac_id 
        and (
            // This wouldn't work with any alias since the required
            // table is pacasso.purchase_product purchasepr3_, which
            // is joined below.
            purchasepr2_.ppr_status <> 'D' 
        )  
left outer join
    pacasso.purchase_product purchasepr3_ 
        on purchasepr2_.ppr_id=purchasepr3_.ppr_id 
where
    this_.mac_code=? 
    and this_.cst_id=?

Am Ende habe ich den @Where aufgegeben Ansatz und verwendet @Filter Stattdessen scheint dies viel besser zu sein, da es HQL anstelle von Datenbankfeldnamen akzeptieren kann und sich bei Anwendung auf Entitätsebene auf Beziehungen auswirkt (im Gegensatz zu @Where ).