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

jua*_*uan 14 java entity hibernate jpa join

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

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

dim*_*mas 18

您可以轻松编写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]);
}
Run Code Online (Sandbox Code Playgroud)

如您所见,查询返回表示每个获取行的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();
Run Code Online (Sandbox Code Playgroud)

这适用于您的情况.


Vla*_*cea 11

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

  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();
    
    Run Code Online (Sandbox Code Playgroud)
  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();
    
    Run Code Online (Sandbox Code Playgroud)

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


usr*_*ΛΩΝ 6

经过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();
Run Code Online (Sandbox Code Playgroud)

或者您可以使用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();
Run Code Online (Sandbox Code Playgroud)

我目前急于尝试新功能.