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