How to join two unrelated entities using JPA and Hibernate

Basically, you have two options:

  1. Since Hibernate 5.1, you can use ad-hoc joins for unrelated entities.

     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. Prior to Hibernate 5.1, you could only use theta-style joins. However, a theta-style join is equivalent to an equijoin, hence you can only emulate INNER JOINs not OUTER JOINs.

     List<Tuple> 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();
    

You can easily write HQL query that will return result as two objects using Theta Join (as Adrian noted). Here is an example:

String queryText = "select address, photo from Address address, Photo photo " 
                 + " where address.personID=photo.personId";
List<Object[]> 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]);
}

As you can see query returns list of Object[] arrays that represents each fetched row. First element of this array will contain one obejct and second element - another.

EDIT:

In case of left join I think you need to use native SQL query (not HQL query). Here how you can do this:

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

List<Object[]> rows = sess.createSQLQuery(queryText)
                          .addEntity("address", Address.class)
                          .addEntity("photo", Photo.class)
                          .list();

This should work for your case.