Hibernate Criteria join query un à plusieurs

J'ai une classe de chat et une classe de propriétaire. Un chat a un propriétaire, mais un propriétaire peut avoir beaucoup de chats. Ce que je veux requête est obtenir tous les propriétaires qui ont un chat aux yeux bleus.

class Cat {
    Owner owner; //referenced from Owner.id
    String eyeColor;
}

class Owner {
    List<Cat> catList;
}

J'ai essayé quelques codes mais je ne sais vraiment pas quoi faire.

Criteria criteria = getCurrentSession().createCriteria(cat.getClass(), "cat");
criteria.createAlias("cat.owner", "owner");    
criteria.add(Restrictions.eq("cat.eyeColor", "blue");
24
demandé sur Roshana Pitigala 2013-07-17 17:31:31

2 réponses

Les critères

Ne peuvent sélectionner que des projections ou l'entité racine. Ce n'est pas quelques a rejoint l'entité. Certaines requêtes sont donc impossibles à exprimer avec des critères (ce qui est une bonne raison de plus d'utiliser HQL, en plus d'une bien meilleure lisibilité et concision).

Tout n'est pas perdu, cependant, parce que votre association est bidirectionnelle. Donc, vous avez juste besoin de l'équivalent de la requête HQL

select distinct owner from Owner owner 
join owner.cats cat 
where cat.eyeColor = 'blue'

Qui est

Criteria c = session.createCriteria(Owner.class, "owner");
c.createAlias("owner.cats", "cat");
c.add(Restrictions.eq("cat.eyeColor", "blue");
c.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
39
répondu JB Nizet 2013-07-17 14:03:13

Essayez ceci:

DetachedCriteria dc = DetachedCriteria.forClass(Cat.class, "inner")
    .add(Restrictions.eq("eyeColor", "blue"))
    .add(Restrictions.eqProperty("inner.owner", "outer.id"));

session.createCriteria(Owner.class, "outer")
    .add(Subqueries.exists(dc))
    .list();

Cela peut utiliser index dans la base de données et ne fera pas une opération en mémoire distinct comme dans la version de @JB Nizet (voir mon commentaire là-bas). L'indice sera:

CREATE INDEX idx_cat_owner_eyecolor ON Cat(fkOwner, eyeColor)

Pensez à l'opération distinct (en SQL ou en mémoire) comme à une odeur de code. Il est rarement utilisé et de nombreux programmeurs novices l'utilisent pour résoudre le problème "pourquoi ai - je cette ligne deux fois". Il peut presque toujours être réécrit comme dans ce cas. Les cas d'utilisation, quand c'est nécessaire, sont peu nombreux.

4
répondu Oliv 2018-05-24 06:43:08