java - tables - inner join hibernate ejemplo
HQL dejó una combinación de entidades no relacionadas (4)
Tengo 2 entidades, A
y B
Están relacionados pero no quiero agregar el mapeo de relación a los beans.
¿Cómo podemos usar la combinación externa izquierda entre A
y B
usando HQL o criterios ?
Hay algunas soluciones disponibles para esto,
- Use Native SQL como se lo dice here .
- Agregue una relación y use seleccionar a de A a left join ab .
- Podemos hacer una combinación interna en el HQL como select * de A a, B b donde a.some = b.some
Siempre regresé estas 2 opciones, ¿hay alguna alternativa para esto? O esto no es posible?
Actualmente, el estilo theta al unir las clases no relacionadas en la cláusula where usando HQL solo admite la unión interna.
La request de soporte de la combinación externa para tal situación es actualmente la tercera mejora más votada, pero no creo que esta característica se implemente en la característica cercana, ya que primero requiere la reimplementación del analizador de consultas basado en ANTLER actual. que parece ser una tarea gigantesca OMI.
Si insiste en usar el HQL para realizar la combinación izquierda sin agregar la relación entre A y B, puede usar la opción 3 para hacer la combinación interna primero, luego use la siguiente HQL
from A a where a.some not in ( select b.some from B)
para descubrir todas las A que no pueden unirse a B y combinar los resultados programáticamente.
Actualizar
A partir del release 5.1.0 HHH-16 (Uniones explícitas en clases no relacionadas) es fijo y deberíamos poder unir las entidades no relacionadas.
Audaz declaración: no puedes.
¿Por qué? JPQL (y HQL) espera una ruta entre las entidades para unirse a ellas.
Lo que suelo hacer en una situación como esta (orden preferente):
- Asociar las entidades.
- Obtenga los datos que necesita para armar los resultados mediante programación.
- Ya sea 1 o 3 de las tres opciones que ya mencionaste.
Como dijo Ken Chan, no se puede hacer directamente en una sola consulta HQL.
En cuanto a tus tres posibilidades:
- SQL nativo: no recomendable. La sintaxis para las uniones externas es bastante diferente entre diferentes bases de datos.
- Agregue una relación: eso es lo que haría. No cuesta mucho código o memoria y se programa rápidamente.
- Unión interna: Eso no funciona (filas faltantes) si la relación realmente es una combinación externa en la base de datos.
Si por algún motivo especial no desea agregar la relación, puede dividirla en dos consultas individuales y unir el resultado manualmente en java, por ejemplo, de esta manera:
Query qa = session.createQuery("from A a");
List la = qa.list();
Query qb = session.createQuery("select distinct b.* from B b, A a where a.some=b.some");
List lb = qb.list();
Map bMap = new HashMap();
for (B b : lb) {
bMap.put(b.getId(), b);
}
/* example with for loop */
for (A a : la) {
B b = bMap.get(a.getForeignKeyForB());
/* now you have A a and the outer joined B b and you can do with them what you want */
...
}
Esta solución tiene (casi) el mismo costo en tiempo de ejecución y memoria que la combinación externa en la base de datos (solución 2.). Es solo un poco más código Java.
(La solución es similar a la propuesta por Ken Chan, pero evita el "no en" y la selección interna, que pueden ser ineficientes en la base de datos).
Si sabe que para cada A hay un máximo de 1 B, también puede usar una subconsulta.
Por ejemplo:
select a, (select b from B b where b.some = a.some)
from A a
Si sabe que existe al menos 1 B, también puede usar la siguiente consulta, pero no se recomienda, ya que es un truco:
select a, (select b4 from B b4 where b4=b and b4.some=a.some) from A a, B b
where a.some=b.some or (a.some not in (select b2.some from B b2)
and b.id = (select min(b3.id) from B b3))