web-dev-qa-db-fra.com

Critères d'hibernation joindre la requête un à plusieurs

J'ai une classe Cat et une classe Owner. Un chat a un propriétaire mais un propriétaire peut avoir plusieurs chats. Ce que je veux interroger 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");
25
hellzone

Les critères ne peuvent sélectionner que les projections ou l'entité racine. Pas une entité jointe. Certaines requêtes sont donc impossibles à exprimer avec Criteria (ce qui est une raison de plus pour utiliser HQL, en plus d'une bien meilleure lisibilité et concision).

Mais tout n'est pas perdu ici, car votre association est bidirectionnelle. Vous avez donc juste besoin de l'équivalent de la requête HQL

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

Lequel 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);
43
JB Nizet

Essaye ça:

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 l'index dans la base de données et ne fera pas d'opération distinct en mémoire comme dans la version de @JB Nizet (voir mon commentaire là-bas). L'index sera:

CREATE INDEX idx_cat_owner_eyecolor ON Cat(fkOwner, eyeColor)

Considérez 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
Oliv