Tengo 2 entidades, A y B. Están relacionadas, pero no quiero agregar que la relación de asignación a los frijoles.

¿Cómo podemos utilizar el left outer join entre A y B utilizando HQL o criterios?

Hay algunas soluciones disponibles para este,

  1. Nativo de SQL como dijo aquí.
  2. Agregar una relación y uso seleccionar una a una a la izquierda unirse a una.b.
  3. Podemos hacer un inner join en el HQL como select * from a a, B b, donde un.algunos=b.algunos

Siempre iba de vuelta de estas 2 opciones, ¿hay alguna alternativa? O no es posible?

InformationsquelleAutor ManuPK | 2012-03-27

4 Comentarios

  1. 56

    Actualmente, el theta de estilo en unirse a la que las clases no relacionadas en la cláusula where utilizando HQL sólo admite inner join.

    La solicitud para apoyar a los outer join para tal situación es actualmente el 3ro más votado de mejora pero no creo que esta característica va a ser implementado en el futuro cercano, ya que requiere el re-implementación de la actual ASTAS de consultas basado en el analizador primera, que parece ser una gigantesca tarea de la OMI.

    Si insisten en el uso de la HQL para realizar left join sin la adición de la relación entre a y B , se puede utilizar la opción 3 para hacer el inner join en primer lugar, a continuación, utilizar la siguiente HQL

    from A a where a.some not in ( select b.some from B)

    para averiguar todos los que no pueden unirse a B y combinar los resultados mediante programación .

    Actualización

    La versión 5.1.0 HHH-16 (Explícito se une en las clases no relacionadas) es fijo y debemos ser capaces de unirse a las entidades no relacionadas.

    • Cristal de sharp. Gracias!
    • Podría apuntar a una fuente para la sintaxis de la nueva «join» opción? Traté de SELECT a FROM A a LEFT JOIN B b ON a.x = b.y y todavía tiene un org.hibernate.hql.internal.ast.QuerySyntaxException: Path expected for join!. (He añadido hibernate-core versión 5.1.0.Final a mi Maven pom archivo, otros artefactos de mi ser en versiones anteriores. Pero como he leído HHH-16, esto debería ser suficiente).
    • Gracias por la actualización y el puntero del asunto cerrado.
    • para mí funciona de esa forma. Tal vez debería ejecutar mvn dependency:tree para comprobar la edad de hibernación versiones y fijarlos con <dependencyManagement>
  2. 3

    Como Ken Chan dijo, no se puede hacer directamente en una sola consulta HQL.

    Concerniente a sus tres posibilidades:

    1. SQL nativo: No recomendable. La sintaxis para las combinaciones externas es bastante diferente entre las diferentes bases de datos.
    2. Agregar una relación: Que es lo que yo haría. No cuesta mucho código o de la memoria, y es rápidamente programado.
    3. Inner join: Que no funciona (falta de filas) si la relación es realmente una combinación externa en la base de datos.

    Si por razones especiales, usted realmente no desea agregar la relación, se puede dividir la consulta en dos consultas individuales y unirse a el resultado manualmente en java, como por ejemplo este:

    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 la memoria como la combinación externa en la base de datos (solución 2.). Es solo un poco más de código java.

    (La solución es similar a la propuesta por Ken Chan, pero evita el «no» y el interior de seleccionar, que tanto puede ser ineficiente en la base de datos.)

  3. 1

    Si usted sabe que para cada Una hay máximo 1 B, también puede utilizar una subconsulta.

    Por ejemplo:

    select a, (select b from B b where b.some = a.some)
    from A a

    Si usted sabe que existe al menos 1 B, también se puede utilizar la siguiente consulta, pero no es recomendable, ya que es un hack:

    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))
    • Wow muchas gracias… esta solucionado mi problema, después de buscar durante 3 días ahora!
  4. -1

    Declaración audaz: no Se puede.

    ¿Por qué? JPQL (y HQL) espera un camino entre las entidades con el fin de unirse a ellos.

    Lo que suele hacer en una situación como esta de (en orden de preferencia):

    1. Asociar la de las entidades.
    2. Obtener los datos que necesita para montar los resultados mediante programación.
    3. 1 o 3 de las tres opciones ya mencionadas.
    • ¿Cuál es la información nueva en esta respuesta? Ya he mencionado estas opciones en la pregunta, y no quiero hacer uso de ellos. espera un camino entre las entidades con el fin de unirse a ellos está mal que puede hacer un inner join, incluso si no hay ninguna asociación.
    • Mis disculpas. Por eso me dijo que era una declaración audaz. Solo para aclarar. Si te refieres a una combinación cruzada con las condiciones (tales como el uso de dos raíces) para lograr la misma cosa como un inner join, entonces, sí, eso es permitido. En realidad unirse (de la Raíz.únete a(…)) es una bestia diferente y eso es lo que usted necesita, o el HQL equivalente, para lograr su objetivo. No he encontrado una solución a este problema hasta ahora. Por lo tanto mi respuesta: no se puede. Tenga en cuenta que me encantaría ser corregido aquí!

Dejar respuesta

Please enter your comment!
Please enter your name here