2012-01-25 18 views
13

Hay una clase Offer que tiene relación opcional con la clase Article. De modo que algunas ofertas de propiedades de artículos tienen un valor de null.Hibernate/JPA: cómo forzar las uniones implícitas para usar UNIONES EXTERNAS IZQUIERDAS

Si uso la siguiente declaración, todo funciona bien. Recibí todas las ofertas, incluso aquellas que no tienen ningún artículo.

SELECT o FROM Offer o 
     LEFT OUTER JOIN o.article a 
     LEFT OUTER JOIN o.vendor v 
     WHERE v.number = '0212' OR a.nummer = '123456' 

si cambio de la declaración:

SELECT o FROM Offer o 
     LEFT OUTER JOIN o.article a 
     LEFT OUTER JOIN o.vendor v 
     WHERE v.number = '0212' OR o.article.nummer = '123456' 

llegué sólo estas ofertas que tienen diferentes artículos de NULL. Esto se debe a que la notación para combinaciones implícitas (o.article.nummer) fuerza una unión interna.

¿Existe la posibilidad de forzar uniones externas izquierdas a uniones implícitas (anotadas o algo por el estilo)? Si hay una posibilidad de que podría utilizar una forma abreviada de esta manera:

SELECT o FROM Offer o 
     WHERE v.number = '0212' OR o.article.nummer = '123456' 

Respuesta

3

Usted puede intentar poner @Fetch(FetchMode.JOIN) en la propiedad del artículo. Esta es una anotación de Hibernate, sin embargo.

import org.hibernate.annotations.Fetch; 
import org.hibernate.annotations.FetchMode; 

//... 

@ManyToOne 
@Fetch(FetchMode.JOIN) 
Article article; 
+0

¡esto no resolvió el problema! –

+0

No sé cómo esto debería resolver el problema.AFAIK Fetchmode solo especifica cómo recuperar los datos para inicializar el objeto en la memoria, no cómo hacer combinaciones en una consulta. –

1

Por lo que podía cavar, Hibernate no lo hace ofrecen una manera de cambiar la forma implícita por defecto de la asociación de unión para un HQL consulta.

Los mejores soluciones que pude encontrar para mí fueron:

  • Construir la consulta con información explícita unirse;
  • Criterios de uso, que probablemente sea mejor para la creación dinámica de consultas.
+0

El OP no dijo que haya algo dinámico. ¿Me he perdido algo? –

+0

El uso de '0212' y '123456' sugiere cambios en la consulta en tiempo de ejecución. Una de las soluciones que encontré para el "uso de la combinación SQL correcta" fue utilizar la API Criteria en su lugar. Y se siente más natural. –

+0

API de criterios suele ser más complicado de usar y menos potente que HQL. Si solo cambian los valores, simplemente ponga los parámetros en la consulta. Esto no es realmente "dinámico", está parametrizado. –

0

En primer lugar, si intenta utilizar o.article.nummer en lugar de a.nummer, creo que incluirá una cláusula WHERE adicional con una unión interna. No hay manera de decir explícitamente uniones a la izquierda. Pero usted mismo lo está especificando en la consulta, así que solo use la entidad unida del alias a.number = '23456'.

Como sabe que el campo es anulable, no puede usar = del mismo modo que no puede usar = en SQL en campos con nulos. En su lugar utilizar unen para convertir los valores NULL a una cadena vacía para este propósito:

SELECT o FROM Offer o 
    LEFT OUTER JOIN o.article a 
    LEFT OUTER JOIN o.vendor v 
     WHERE v.number = '0212' 
     OR COALESCE(a.nummer,'') = '123456' 
0

que tenía un problema similar: Yo tenía una especie de GeneralFacility -Tabla que contenía una columna SpecificType. No todas las instalaciones tenían este tipo y como el SpecificType se unió internamente en las entradas de GeneralFacility-Table sin un tipo específico cayó bajo la mesa.

me resolvió el problema poniendo

@Fetch(FetchMode.SELECT) 

junto a la @ManyToOne -line en el modelo. El tipo ahora se obtiene en una consulta separada y, si eso no devuelve nada, los resultados de la consulta GeneralFacility NO se descartan.

+0

Supongo que esto solo se aplica cuando recuperas la entidad, p. usando 'session.get'. Cuando necesita la propiedad en una consulta HQL, no tiene influencia hasta donde yo sé. –

Cuestiones relacionadas