Criterios de hibernación join query uno a muchos


Tengo una clase de Gato y una clase de Propietario. Un gato tiene un dueño, pero un dueño puede tener muchos gatos. Lo que quiero consultar es obtener todos los propietarios que tienen un gato con ojos azules.

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

class Owner {
    List<Cat> catList;
}

Probé algunos códigos, pero realmente no sé qué hacer.

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

2 answers

Los criterios solo pueden seleccionar proyecciones, o la entidad raíz. No una entidad unida. Por lo tanto, algunas consultas son imposibles de expresar con Criterios (que es una buena razón más para usar HQL, además de una mejor legibilidad y concisión).

No todo está perdido aquí, sin embargo, porque su asociación es bidireccional. Por lo tanto, solo necesita el equivalente de la consulta HQL

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

Que es

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
Author: JB Nizet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-17 14:03:13

Prueba esto:

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();

Esto puede usar index en la base de datos y no hará una operación in-memory distinct como en la versión de @JB Nizet (ver mi comentario allí). El índice será:

CREATE INDEX idx_cat_owner_eyecolor ON Cat(fkOwner, eyeColor)

Piense en la operación distinct (ya sea en SQL o en memoria) como en un olor a código. Rara vez se usa y muchos programadores novatos lo usan para solucionar el problema "por qué tengo esta fila dos veces". Casi siempre se puede reescribir como en este caso. Los casos de uso, cuando es necesario, son pocos.

 4
Author: Oliv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-24 06:43:08