Hibernate discriminator v OUTER JOIN
Rastislav Siekel
siekel na prosoft.sk
Čtvrtek Září 17 09:55:45 CEST 2009
Roman,
díky za príspevok, ale v tomto prípade filter použiť nejde. Ako ste
správne poznamenali, filter sa dá použiť na celý Class alebo
Collections, lenže ja mám many-to-one väzbu. A nemôžem mať množinu
RECORD-ov v entite LOG, pretože hľadám práve také, ktoré ešte nemajú
záznam v LOG.
Aj tak díky moc,
Rastislav "Bedo" Siekel
Roman Zakutny wrote:
> Zdravim,
>
> odhliadnuc od toho, ci Vase riesenie nie je zbytocne komplikovane,
> kedze nepoznam pozadie celeho problemu, sam som sa pred par mesiacmi
> taktiez stretol s absenciou moznosti pridat na ktorykolvek JOIN v
> dotaze vlastnu ON podmienku v Criteria API. O moznosti "with" som
> vedel, avsak HQL som sa pokial mozno chcel naozaj vyhnut. Na moje
> prekvapenie ta podpora tam bohuzial nebola (ak ak bola alebo uz je,
> budem velmi rad, ze ma niekto z tohoto omylu vyvedie:) Hibernate vsak
> ponuka riesenie a ja som ho vyuzil. Uz si detaily nepamatam, takze
> neviem presne povedat, aky to ma dopad na vykon. Nepouzival som ziadne
> FORMULA ani DISCRIMINATOR features, ale jednoduchy FILTER COLLECTIONS.
> Ide o to, ze ak chcete obmedzit nejaku podmnozinu dat, tak vo vysledku
> sa tato podmnozina typicky prejavi ako nejaka Collection v entite (vo
> Vasom pripade by to bolo Records v Log entite). Samotny dotaz je bez
> podmienok a vzhladom na to, ze vysledna Collection bude typicky LAZY
> natiahnuta, tak nasledujuce filtrovanie sa prevadza este v pamati bez
> pristupu do databazy, co oni oznacuju za velmi efektivny sposob. Ked
> potom pristupujete na jednotlive prvky kolekcie, tie uz splnaju Vami
> zadane kriteria. Takze taky workaround na ON podmienku...
>
> Doporucujem si pozriet velmi jednoduchy priklad:
> http://www.javalobby.org/java/forums/t43955.html
>
> Na moj problem som si s tym bez problemov vystacil a nemusel som
> pouzit HQL. Chapem, ze pre komplikovane podmienky napriec roznymi
> entitami v dotaze toto pouzitie nemusi byt jednoduche, ba dokonca
> nemozne...
>
> S pozdravom Roman.
>
> On Wed, 16 Sep 2009 22:44:30 +0200, Lukas Barton <lukas na cnawr.cz> wrote:
>
>> Proc proste nenapisete:
>> select Record1 from Record1 where not exists(select Log.id from Log
>> where Log.id = Record1.id and Log.type = "TL")
>>
>> Nemusite nic znasilnovat a je to i srozumitelnejsi.
>>
>> On 9/16/09, Rastislav Siekel <siekel na prosoft.sk> wrote:
>>> Ahojte,
>>>
>>> nevedel by niekto poradiť ako dostanem v Hibernate podmienku do
>>> klauzuly
>>> ON pre outer join?
>>>
>>> Mám tabuľky záznamov - napr. RECORD1, RECORD2, ... a jednu tabuľku
>>> logov
>>> - napr. LOG , kde si poznačím, ktoré záznamy a akého typu už boli
>>> spracované.
>>> Na úvod hľadám záznamy, ktoré ešte neboli vôbec spracované a preto v
>>> tabuľke LOG nie sú. Typ záznamu hľadám napr. 'TL' a tie sú v tabuľke
>>> RECORD1.
>>>
>>>
>>> Potrebujem vygenerovať asi takýto SELECT:
>>> *select RECORD1.*
>>> from LOG
>>> right outer join RECORD1 on (**LOG.TYPE= 'TL' and
>>> **RECORD1.ID=**LOG.ID**)
>>> where LOG.ID is null
>>> *
>>>
>>> Hibernate som najprv znásilnil cez <formula>, aby mi to generoval, asi
>>> takto:
>>> *<class name="log" table="LOG" >
>>> <id name=... />
>>>
>>> <property name="record1_Id" column="RECORD1_ID" type=... />
>>>
>>> <many-to-one name="record1" column="RECORD1_ID" class=... />
>>> <formula>LOG_TYPE='TL' and RECORD1_ID</formula>
>>> </many-to-one>
>>>
>>> ...
>>> </class>
>>>
>>> *Toto fungovalo a všetko bolo v poriadku. Potom však prišla požiadavka
>>> čítať záznamy z LOG-u a pre takéto mapovanie sa tá <formula> ocitla v
>>> SELECT liste, čo samozrejme spôsobilo neplatné SQL.
>>>
>>> Pokúšal som sa uvedené mapovanie zmeniť pomocou DISCRIMINATOR-a a
>>> nového
>>> potomka triedy LOG (napr. logExt) nejako takto:
>>> *<class name="log" table="LOG" >
>>> <id name=... />
>>>
>>> <discriminator column="LOG_TYPE" type="string" length="2" />
>>>
>>> <property name="record1_Id" column="RECORD1_ID" type=... />
>>>
>>> <subclass name="logExt" discriminator-value="TL">
>>> ** <many-to-one name="record1" column="RECORD1_ID"
>>> class=... />
>>> ** </subclass>
>>>
>>> ...
>>> </class>
>>> *
>>> Čo však vygenerovalo takýto SQL:
>>> *select RECORD.ID, ...
>>> from LOG
>>> right outer join RECORD on LOG.ID=RECORD.ID
>>> where LOG.ID is null ** and **LOG.TYPE= 'TL'
>>>
>>> *Čiže podmienka *LOG.TYPE= 'TL'* sa ocitla vo WHERE a nie v ON
>>> klauzule,
>>> čo má samozrejme fatálny vplyv na výsledok, pretože ak LOG je null, tak
>>> podmienka na LOG.TYPE je vždy FALSE a vráti sa prázdna množina.
>>>
>>> Priateľ google napovedal, že Gavin 26.8.2003 tvrdil, že mapovanie
>>> *<discriminator>* s atribútom *force="true"* prinesie tento
>>> diskriminator do ON klauzuly - viď
>>> https://forum.hibernate.org/viewtopic.php?f=1&t=934203&view=next
>>> ale mne sa to takto nechová.
>>>
>>>
>>> Teraz mi ostali asi 2 možnosti riešenia, ale ani jedna sa mi nepozdáva.
>>>
>>> 1. Vytvoriť dve mapovania (trebárs ako predok a potomok), kde do
>>> potomka dám uvedené hack-y typu <formula> a keď budem chcieť
>>> čítať
>>> záznamy z LOG-u, budem čítať predka.
>>> 2. Použiť v HQL klauzulu WITH, ktorá dáva podmienku do ON klauzuly,
>>> ale musel by som zmeniť smer mapovania - RECORD by mal namapovaný
>>> LOG, čo je logicky zle, lebo entita RECORD nemá nič vedieť o tom,
>>> že si ju niekto loguje.
>>>
>>>
>>> Neviete niekto ešte inú možnosť?
>>>
>>> Rastislav "Bedo" Siekel
>>>
>>> P.S. Hibernate 3.2.1.ga voči Oracle 10.
------------- další část ---------------
HTML příloha byla odstraněna...
URL: <http://amaio.cz/pipermail/konference/attachments/20090917/ffbc348c/attachment.htm>
Další informace o konferenci Konference