繁体   English   中英

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

[英]How to join two unrelated entities using JPA and Hibernate

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

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

您可以使用 Theta Join 轻松编写将结果作为两个对象返回的 HQL 查询(如 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[] 数组列表。 该数组的第一个元素将包含一个对象和第二个元素 - 另一个。

编辑:

在左连接的情况下,我认为您需要使用本机 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. 从 Hibernate 5.1 开始,您可以对不相关的实体使用临时连接

     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 样式的连接。 但是,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();

12 年后,Hibernate 团队终于实现了这样的功能

来自Hibernate 文档

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 子句的条件成为生成的 SQL 中 ON 子句的一部分,这与本节中的其他查询相反,其中 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();

我目前很想尝试新功能。

在 Hibernate 5.1 中可以连接两个不相关的实体。

例如:

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

你要找的是

  1. 高质量语言
  2. 加入您尚未建模为关系的字段
  3. 左连接

(在第一次提出问题并给出答案时) Hibernate 支持 Theta Join,它允许您执行 1 和 2。但是,只有内部联接可用于 theta 联接样式。

我个人建议您建立适当的关系模型,因此您只需要 1 和 3,这在 HQL 中得到了很好的支持。

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

最好有一个包含您要加入的那些类的类,以便将它们全部放在一起。

但是,如果您只是出于某些偶然目的加入这些表,则可以使用条件并手动从每个表中加载数据并将它们放在一起。 (是的,如果 Address 和 Photo 有两个单独的类和表,您可以分别拥有这些表的数据)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM