14.10. Expressions

Les expressions permises dans la clause where incluent la plupart des choses que vous pouvez utiliser en SQL :

in et between peuvent être utilisés comme suit :

from DomesticCat cat where cat.name between 'A' and 'B'
from DomesticCat cat where cat.name in ( 'Foo', 'Bar', 'Baz' )

et la forme négative peut être écrite

from DomesticCat cat where cat.name not between 'A' and 'B'
from DomesticCat cat where cat.name not in ( 'Foo', 'Bar', 'Baz' )

De même, is null et is not null peuvent être utilisés pour tester les valeurs nulle.

Les booléens peuvent être facilement utilisés en déclarant les substitutions de requêtes dans la configuration Hibernate :

<property name="hibernate.query.substitutions">true 1, false 0</property>

Ce qui remplacera les mots clés true et false par 1 et 0 dans la traduction SQL du HQL suivant :

from Cat cat where cat.alive = true

Vous pouvez tester la taille d'une collection par la propriété spéciale size, ou la fonction spéciale size().

from Cat cat where cat.kittens.size > 0
from Cat cat where size(cat.kittens) > 0

Pour les collections indexées, vous pouvez faire référence aux indices minimum et maximum en utilisant les fonctions minindex and maxindex. De manière similaire, vous pouvez faire référence aux éléments minimum et maximum d'une collection de type basiques en utilisant les fonctions minelement et maxelement.

from Calendar cal where maxelement(cal.holidays) > current_date
from Order order where maxindex(order.items) > 100
from Order order where minelement(order.items) > 10000

Les fonctions SQL any, some, all, exists, in supportent que leur soient passées l'élément, l'index d'une collection (fonctions elements et indices) ou le résultat d'une sous requête (voir ci dessous).

select mother from Cat as mother, Cat as kit
where kit in elements(foo.kittens)
select p from NameList list, Person p
where p.name = some elements(list.names)
from Cat cat where exists elements(cat.kittens)
from Player p where 3 > all elements(p.scores)
from Show show where 'fizard' in indices(show.acts)

Notez que l'écriture de - size, elements, indices, minindex, maxindex, minelement, maxelement - peuvent seulement être utilisée dans la clause where dans Hibernate3.

Les éléments de collections indexées (arrays, lists, maps) peuvent être référencés via index (dans une clause where seulement) :

from Order order where order.items[0].id = 1234
select person from Person person, Calendar calendar
where calendar.holidays['national day'] = person.birthDay
    and person.nationality.calendar = calendar
select item from Item item, Order order
where order.items[ order.deliveredItemIndices[0] ] = item and order.id = 11
select item from Item item, Order order
where order.items[ maxindex(order.items) ] = item and order.id = 11

L'expression entre [] peut même être une expression arithmétique.

select item from Item item, Order order
where order.items[ size(order.items) - 1 ] = item

HQL propose aussi une fonction index() interne, pour les éléments d'une association one-to-many ou d'une collections de valeurs.

select item, index(item) from Order order
    join order.items item
where index(item) < 5

Les fonctions SQL scalaires supportées par la base de données utilisée peuvent être utilisées

from DomesticCat cat where upper(cat.name) like 'FRI%'

Si vous n'êtes pas encore convaincu par tout cela, imaginez la taille et l'illisibilité qui caractériseraient la transformation SQL de la requête HQL suivante :

select cust
from Product prod,
    Store store
    inner join store.customers cust
where prod.name = 'widget'
    and store.location.name in ( 'Melbourne', 'Sydney' )
    and prod = all elements(cust.currentOrder.lineItems)

Un indice : cela donnerait quelque chose comme

SELECT cust.name, cust.address, cust.phone, cust.id, cust.current_order
FROM customers cust,
    stores store,
    locations loc,
    store_customers sc,
    product prod
WHERE prod.name = 'widget'
    AND store.loc_id = loc.id
    AND loc.name IN ( 'Melbourne', 'Sydney' )
    AND sc.store_id = store.id
    AND sc.cust_id = cust.id
    AND prod.id = ALL(
        SELECT item.prod_id
        FROM line_items item, orders o
        WHERE item.order_id = o.id
            AND cust.current_order = o.id
    )