2011-07-02 7 views
6

¿Cómo puedo escribir una consulta de Hibernate Criteria para una superclase y verificar cierta subclase? Imaginemos que tenemos las siguientes clases todo planeado con Hibernate-JPA:¿Cómo puedo escribir una consulta de criterios de Hibernación para una súper clase y verificar cierta subclase?

@Entity 
@Inheritance(strategy = InheritanceType.JOINED) 
public class Bar { 
    @Id 
    @Column(name = "id") 
    private Long id; 
} 

@Entity 
@PrimaryKeyJoinColumn(name="bar_id") 
public class Foo extends Bar { 
} 

@Entity 
@PrimaryKeyJoinColumn(name="bar_id")  
public class Goo extends Bar { 
} 

Al escribir una consulta criterios como éste, me gustaría, por su rendimiento, utilizar una izquierda a unirse con la sub-clase:

getSession() 
    .createCriteria(Bar.class) 
    .createAlias("Foo", "foo", CriteriaSpecification.LEFT_JOIN) 
    .add(Restrictions.isNotNull("foo.bar_id")) 
    .list(); 

Esto falla, porque la ruta de asociación "Foo" no funciona, obviamente, pero ilustrará lo que quiero. ¿O hay otra forma de hacer este tipo de consulta? Necesito que la consulta se realice en la superclase. Si yo lo hubiera hecho en SQL que se vería así:

select b.* 
from bar b left join foo f on f.bar_id = b.id 
where f.bar_id is not null; 

La consulta SQL anterior es sólo para ilustrar lo que quiero decir, sé que sería más fácil de usar un "normal" unirse en ese caso concreto .

Respuesta

7

Realmente no está claro lo que quieres hacer.

En primer lugar, como Foo hereda de Bar, la búsqueda de instancias de Bar devolverá automáticamente las instancias de Foo. Hibernate se encarga de unirse a las mesas por sí mismo.

Segundo: su consulta SQL es realmente extraña. Estás haciendo un join a la izquierda (lo que significa que estás buscando barras que podrían no tener un foo asociado), pero también tienes un where en donde foo.bar_id no es nulo. Este hecho constituye una combinación interna, y podría reescribirse como

select b.* from bar b inner join foo f on f.bar_id = b.id 

Si lo que quieres hacer es buscar Foos, y sólo Foos, a continuación, utilizar un Criterios de Foo como entidad raíz:

getSession() 
    .createCriteria(Foo.class) 
    .list(); 

Obtendrás instancias de Foo, pero como Foo amplía Bar, estas instancias de Foo también son instancias de Bar. Eso es lo que es la herencia.

Ahora bien, si usted está construyendo su instancia Criterios de forma dinámica, y darse cuenta en algún momento que la búsqueda sólo debe devolver las instancias de Foo, usted tiene que utilizar la propiedad clase implícita:

Criteria c = getSession().createCriteria(Bar.class, "bar") 
// ... 
if (limitToFoos) { 
    c.add(Restrictions.eq("bar.class", Foo.class)); 
} 
+0

Sí que sé sobre el Consulta SQL, fue solo para ilustrar el punto y aclarar la pregunta. Mi consulta es mucho más compleja IRL. Sin embargo, agregar una restricción para la propiedad de la clase funciona perfectamente. Muy lógico cuando lo piensas, gracias. – crunchdog

+0

'Restrictions.eq (" bar.class ", Foo.class))' era lo que estaba buscando, ¡gracias! – jlb

Cuestiones relacionadas