[Hibernate] query op collectie

Pagina: 1
Acties:

  • Cuball
  • Registratie: Mei 2002
  • Laatst online: 16:37
Ik vroeg me af of het mogelijk is om met HQL selecties te doen op een parent object afhankelijk van wat er in een collectie van dit parent object zit:

stel ik heb een Order met een lijst van OrderLines, laten we nu stellen dat deze bv een naam heeft.
code:
1
2
3
4
5
6
7
class Order {
List OrderLines;
}

class OrderLine {
String name;
}


nu wil ik via HQL een lijst van Orders terug krijgen waar name in orderline like %test% is.

Als ik een join op OrderLines doe lukt dit wel, maar is enkel nuttig om deze collectie al mee op te halen in men Order object en niet de bedoeling dat je daarop selecties gaat doen.
Dit geeft als resultaat een lijst van Array's terug en niet een lijst van Orders...

Nu doe ik het via een subselect maar is niet echt performant...

"Live as if you were to die tomorrow. Learn as if you were to live forever"


  • whoami
  • Registratie: December 2000
  • Laatst online: 16:54
men Order
:?

Hoe ziet jouw HQL er dan nu precies uit ?
Als je dit doet:
code:
1
IQuery q = sessionObj.CreateQuery ("select o.* from Order as o, OrderLine as ol where .....");

Krijg je dan niet de Order objecten die je wilt ?
Als je OrderLines niet lazy loaded zijn, dan zullen de OrderLines er ook bij zitten; wil je dat niet, dan kan je die lazy-loaden.

https://fgheysels.github.io/


  • Gert
  • Registratie: Juni 1999
  • Laatst online: 05-12-2025
Java:
1
2
3
4
5
List cats = sess.createCriteria(Cat.class)
    .add( Restrictions.like("name", "F%") )
    .createCriteria("kittens")
        .add( Restrictions.like("name", "F%") )
    .list();


Zo kan het in ieder geval wel. Zover ik mij herinner kan je gewoon order.collectie.property gebruiken in je hql query.

  • matthijsln
  • Registratie: Augustus 2002
  • Laatst online: 12:01
Je zou ook exists kunnen gebruiken als een where conditie (alleen indien je relatie bidirectioneel is):

from Order o where exists (select 1 from OrderLine ol where ol.order = o and ol.name like '%test%')
Of:
from Order o where o in (select ol.order from OrderLine ol where ol.name like '%test%')

Met een join is wel een distinct nodig omdat je voor elke OrderLine die matcht ook je Order weer in het resultaat krijgt:

select distinct o from Order o join o.orderlines ol where ol.name like '%test%'

  • whoami
  • Registratie: December 2000
  • Laatst online: 16:54
matthijsln schreef op woensdag 12 april 2006 @ 11:57:

Met een join is wel een distinct nodig omdat je voor elke OrderLine die matcht ook je Order weer in het resultaat krijgt:

select distinct o from Order o join o.orderlines ol where ol.name like '%test%'
hoezo ? Hibernate zal toch wel zo slim zijn om één Order instantie te maken, met daaraan de gekoppelde OrderLines ?

https://fgheysels.github.io/


  • Cuball
  • Registratie: Mei 2002
  • Laatst online: 16:37
whoami schreef op woensdag 12 april 2006 @ 11:39:
[...]
:?

Hoe ziet jouw HQL er dan nu precies uit ?
zoals matthijsln geschreven heeft doe ik het nu:

code:
1
from Order o where o in (select ol.order from OrderLine ol where ol.name like '%test%')


maar ik kan met niet voorstellen dat een een in met meer dan 50.000 waarden echt performant zal zijn :(

[ Voor 4% gewijzigd door Cuball op 12-04-2006 12:08 ]

"Live as if you were to die tomorrow. Learn as if you were to live forever"


  • Varienaja
  • Registratie: Februari 2001
  • Laatst online: 14-06-2025

Varienaja

Wie dit leest is gek.

Cuball schreef op woensdag 12 april 2006 @ 12:07:
zoals matthijsln geschreven heeft doe ik het nu:

code:
1
from Order o where o in (select ol.order from OrderLine ol where ol.name like '%test%')
Waarom niet gewoon zo:
code:
1
select ol.order from OrderLine ol where ol.name like '%test%
maar ik kan met niet voorstellen dat een een in met meer dan 50.000 waarden echt performant zal zijn :(
Analyseer de gegenereerde SQL. En controleer of je vermoeden juist is. Vind daarna de bottleneck, en ruim 'm uit de weg.

Siditamentis astuentis pactum.


  • Cuball
  • Registratie: Mei 2002
  • Laatst online: 16:37
whoami schreef op woensdag 12 april 2006 @ 12:00:
[...]

hoezo ? Hibernate zal toch wel zo slim zijn om één Order instantie te maken, met daaraan de gekoppelde OrderLines ?
blijkbaar niet, er moet inderdaad distinct bijkomen

"Live as if you were to die tomorrow. Learn as if you were to live forever"


  • matthijsln
  • Registratie: Augustus 2002
  • Laatst online: 12:01
whoami schreef op woensdag 12 april 2006 @ 12:00:
[...]

hoezo ? Hibernate zal toch wel zo slim zijn om één Order instantie te maken, met daaraan de gekoppelde OrderLines ?
Nee, je krijgt voor elke OrderLine die matcht een Order terug, dus het kan zijn dat je meerdere dezelfde Order objecten in het resultaat krijgt (wel dezelfde instantie). Dat is de semantiek van de expressie (Hibernate maakt er namelijk gewoon een join van zoals in jouw query). Misschien niet helemaal intuitief op het eerste gezicht.

Wil je geen dubbele instanties moet je dus of distinct of een conditie op de orderlines collectie in een subselect zodat één Order maar één keer wordt geevalueerd of deze aan de query conditie voldoet.

  • Cuball
  • Registratie: Mei 2002
  • Laatst online: 16:37
Varienaja schreef op woensdag 12 april 2006 @ 12:13:
[...]

Waarom niet gewoon zo:
code:
1
select ol.order from OrderLine ol where ol.name like '%test%
zo heb ik het nog niet bekekijken, maar het lijkt wat omgekeerd werken, via je OrderLine geef je een Order object terug... alle andere restricties die op Order komen moet ik dan via OrderLine benaderen, hierdoor lukken ook niet alle query's even goed

[ Voor 4% gewijzigd door Cuball op 12-04-2006 12:23 ]

"Live as if you were to die tomorrow. Learn as if you were to live forever"


  • Cuball
  • Registratie: Mei 2002
  • Laatst online: 16:37
Ik kom nu nog een probleem tegen, het startvoorbeeld dat ik gaf is niet volledig:
OrderLine bevat nog een many-to-one relatie naar een Persoon object

Java:
1
2
3
4
5
6
class OrderLine {
Persoon persoon;
}
class Persoon {
string name;
}


ik moet dus like op name in persoon doen.

Volgende query geeft een invalid path op orderLines.persoon.name:

Java:
1
select distinct o from Order o join o.orderLines orderLines where orderLines.persoon.name like '%test%' 

ik verwar HQL joins toch soms wat teveel met gewone SQL joins denk ik...

"Live as if you were to die tomorrow. Learn as if you were to live forever"


  • matthijsln
  • Registratie: Augustus 2002
  • Laatst online: 12:01
Cuball schreef op woensdag 12 april 2006 @ 12:32:
Ik kom nu nog een probleem tegen, het startvoorbeeld dat ik gaf is niet volledig:
OrderLine bevat nog een many-to-one relatie naar een Persoon object

Java:
1
2
3
4
5
6
class OrderLine {
Persoon persoon;
}
class Persoon {
string name;
}


ik moet dus like op name in persoon doen.

Volgende query geeft een invalid path op orderLines.persoon.name:

Java:
1
select distinct o from Order o join o.orderLines orderLines where orderLines.persoon.name like '%test%' 

ik verwar HQL joins toch soms wat teveel met gewone SQL joins denk ik...
Dit moet gewoon werken, maar probeer eens met een alias dat niet hetzelfde is als een andere naam:

select distinct o from Order o join o.orderLines orderLine where orderLine.persoon.name like '%test%'

  • Cuball
  • Registratie: Mei 2002
  • Laatst online: 16:37
matthijsln schreef op woensdag 12 april 2006 @ 12:40:

Dit moet gewoon werken, maar probeer eens met een alias dat niet hetzelfde is als een andere naam:

select distinct o from Order o join o.orderLines orderLine where orderLine.persoon.name like '%test%'
werkt ook niet, het volgende werkt dus wel:

code:
1
select distinct o from Order o join o.orderLines.persoon p where p.firstName like '%test%'

[ Voor 4% gewijzigd door Cuball op 12-04-2006 12:49 ]

"Live as if you were to die tomorrow. Learn as if you were to live forever"


  • Varienaja
  • Registratie: Februari 2001
  • Laatst online: 14-06-2025

Varienaja

Wie dit leest is gek.

Cuball schreef op woensdag 12 april 2006 @ 12:48:
werkt ook niet, het volgende werkt dus wel:
code:
1
select distinct o from Order o join o.orderLines.persoon p where p.firstName like '%test%'
Is dat wel correct? Join je nu niet alle personen met alle orders waarvan de persoon z'n naam "test" bevat?Laat maar.. ik kan gewoon join-queries niet goed lezen ;)

Zo is het toch weer korter:
code:
1
select distinct ol.order from OrderLine ol where ol.persoon.firstName like '%test%'


En ook dit kan:
code:
1
select distinct o from Order o, OrderLine ol where ol.id in elements(o.orderLines) and ol.persoon.Firstname like '%test%'

[ Voor 9% gewijzigd door Varienaja op 12-04-2006 14:16 ]

Siditamentis astuentis pactum.

Pagina: 1