Saltar al contenido

Cómo unir dos entidades no relacionadas usando JPA e Hibernate

El paso a paso o código que encontrarás en este post es la resolución más sencilla y efectiva que encontramos a esta duda o dilema.

Solución:

Puede escribir fácilmente una consulta HQL que devolverá el resultado como dos objetos usando Theta Join (como señaló Adrian). Aquí hay un ejemplo:

String queryText = "select address, photo from Address address, Photo photo " 
                 + " where address.personID=photo.personId";
List rows = session.createQuery(queryText).list();

for (Object[] row: rows) 
    System.out.println(" ------- ");
    System.out.println("Address object: " + row[0]);
    System.out.println("Photo object: " + row[1]);

Como puede ver, la consulta devuelve la lista de objetos[] matrices que representan cada fila recuperada. primer elemento de este array contendrá un objeto y un segundo elemento, otro.

EDITAR:

En el caso de la combinación izquierda, creo que debe usar una consulta SQL nativa (no una consulta HQL). Aquí cómo puedes hacer esto:

String queryText = "select address.*, photo.* from ADDRESS address 
                    left join PHOTO photo on (address.person_id=photo.person_id)";

List rows = sess.createSQLQuery(queryText)
                          .addEntity("address", Address.class)
                          .addEntity("photo", Photo.class)
                          .list();

Esto debería funcionar para su caso.

Básicamente, tienes dos opciones:

  1. Desde Hibernate 5.1, puede usar uniones ad-hoc para entidades no relacionadas.

     Tuple postViewCount = entityManager.createQuery(
         "select p as post, count(pv) as page_views " +
         "from Post p " +
         "left join PageView pv on p.slug = pv.slug " +
         "where p.title = :title " +
         "group by p", Tuple.class)
     .setParameter("title", "High-Performance Java Persistence")
     .getSingleResult();
    
  2. Antes de Hibernate 5.1, solo podía usar uniones de estilo theta. Sin embargo, una combinación de estilo theta es equivalente a una combinación igualitaria, por lo tanto, solo puede emular INNER JOIN, no OUTER JOIN.

     List postViewCount = entityManager.createQuery(
         "select p as post, count(pv) as page_views " +
         "from Post p, PageView pv " +
         "where p.title = :title and " +
         "      ( p.slug = pv.slug ) " +
         "group by p", Tuple.class)
     .setParameter("title", "Presentations")
     .getResultList();
    

Finalmente, después de 12 años, el equipo de Hibernate ha implementado dicha función.

De los documentos de Hibernate:

La cláusula FROM también puede contener uniones de relaciones explícitas utilizando la palabra clave de unión. Estas uniones pueden ser uniones de estilo interno o externo izquierdo.

List persons = entityManager.createQuery(
    "select distinct pr " +
    "from Person pr " +
    "join pr.phones ph " +
    "where ph.type = :phoneType", Person.class )
.setParameter( "phoneType", PhoneType.MOBILE )
.getResultList();


List persons = entityManager.createQuery(
    "select distinct pr " +
    "from Person pr " +
    "left join pr.phones ph " +
    "where ph is null " +
    "   or ph.type = :phoneType", Person.class )
.setParameter( "phoneType", PhoneType.LAND_LINE )
.getResultList();

O puedes usar WITH y ON palabras clave Una observación sobre esos

La distinción importante es que en el SQL generado, las condiciones de la cláusula WITH/ON forman parte de la cláusula ON en el SQL generado, a diferencia de las otras consultas de esta sección, donde las condiciones HQL/JPQL forman parte del WHERE. cláusula en el SQL generado.

Ejemplo

List personsAndPhones = session.createQuery(
    "select pr.name, ph.number " +
    "from Person pr " +
    "left join pr.phones ph with ph.type = :phoneType " )
.setParameter( "phoneType", PhoneType.LAND_LINE )
.list();

Actualmente estoy ansioso por probar la nueva función.

Si te sientes impulsado, tienes la opción de dejar un enunciado acerca de qué te ha impresionado de este ensayo.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *