如何使用JPA和Hibernate加入两个不相关的实体

我有两个表 – 一个包含地址,另一个包含照片。 它们之间唯一的共同点是PersonID。 这些映射到两个POJO类地址和照片。 我可以通过创建条件并在字段上添加限制来获取这些表中的详细信息。 我们应该如何在两个表上编写连接。 是否可以将结果作为两个对象-Address和Photo。

我想做一个左连接,这样我就可以获得没有照片的人的记录。 我已经读过这可能只使用hql但是这可以使用标准来完成吗?

您可以轻松编写HQL查询,该查询将使用Theta Join将结果返回为两个对象(如Adrian所述)。 这是一个例子:

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]); } 

如您所见,查询返回表示每个获取行的Object []数组列表。 该数组的第一个元素将包含一个obejct和第二个元素 – 另一个元素。

编辑:

在左连接的情况下,我认为您需要使用本机SQL查询(而不是HQL查询)。 在这里你可以这样做:

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

这适用于您的情况。

正如我在本文中解释的那样,您有两种选择:

  1. 从Hibernate 5.1开始,您可以为不相关的实体使用ad-hoc连接 。

     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. 在Hibernate 5.1之前,您只能使用theta样式的连接。 但是,θ样式连接相当于等值连接,因此您只能模拟INNER JOIN而不是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(); 

有关更多详细信息,请查看此文章 。

经过12年的努力,Hibernate团队已经实现了这样的function

来自Hibernate的文档 :

FROM子句还可以使用join关键字包含显式关系连接。 这些连接可以是内部或左外部样式连接。

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

或者您可以使用WITHON关键字。 这些评论

重要的区别在于,在生成的SQL中,WITH / ON子句的条件成为生成的SQL中ON子句的一部分,而不是本节中将HQL / JPQL条件作为WHERE的一部分的其他查询生成的SQL中的子句。

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

我目前急于尝试新function。

在Hibernate 5.1中可以加入两个不相关的实体。

例如:

 select objA from ObjectA objA JOIN ObjectB objB on objB.variable = objA.variable where objA.id = 1 

最好有一个包含你想要加入的类的类,将它们放在一起。

但是,如果您仅为偶尔的目的加入这些表,则可以使用条件并手动加载每个表中的数据并将它们放在一起。 (是的,如果地址和照片有两个单独的类和表,你可以单独拥有这些表的数据)

你在寻找什么

  1. HQL
  2. 加入您尚未建模为关系的字段
  3. 左加入

(在第一次询问问题并给出这个答案的时候) Hibernate支持Theta Join,它允许你做1和2.但是,只有内连接可用于theta join样式。

我个人建议你建立适当的关系,所以你只需要1和3,这在HQL中得到了很好的支持。

(另一个答案实际上提供了新的Hibernatefunction的更新,提供了这样的function,您可以简单地参考)