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

时间:2012-08-06 03:39:15

标签: java hibernate jpa join entity

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

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

6 个答案:

答案 0 :(得分:16)

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

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

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

修改

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

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

这适用于您的情况。

答案 1 :(得分:10)

正如我在this article中所解释的,您有两种选择:

  1. 从Hibernate 5.1开始,您可以将ad-hoc joins用于不相关的实体。

    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<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();
    
  3. 有关详细信息,请查看this article

答案 2 :(得分:6)

12年后,Hibernate团队已经implemented such a feature

来自Hibernate docs

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

List<Person> 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<Person> 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子句的一部分是生成的ON子句的一部分   SQL,而不是本节中的其他查询所在的   HQL / JPQL条件是生成的WHERE子句的一部分   SQL。

实施例

List<Object[]> 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();

我目前急于尝试新功能。

答案 3 :(得分:3)

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

例如:

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

答案 4 :(得分:0)

您正在寻找的是

  1. HQL
  2. 加入尚未建模为关系的字段
  3. 左加入
  4. (在第一次询问问题时给出了这个答案) Hibernate支持Theta Join,它允许你做1&amp; 2.但是,只有内连接可用于theta连接样式。

    就我个人而言,我建议你建立适当的关系,所以你只需要1&amp; 3在HQL中得到了很好的支持。

    (另一个答案实际上提供了关于提供此类功能的新Hibernate功能的更新,您可以简单地参考)

答案 5 :(得分:0)

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