如何使用 JPA 和 Hibernate 连接两个不相关的实体

2022-09-02 11:53:20

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

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


答案 1

您可以轻松编写 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();

这应该适用于您的情况。


答案 2

基本上,您有两种选择:

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

推荐