我有两张表 - 一张包含地址,另一张包含照片。它们之间唯一的共同字段是 PersonID。这些被映射到两个 POJO 类地址和照片。我能够通过创建条件和对字段添加限制来获取这些表中的详细信息。我们应该如何在两个表上编写连接。是否可以将结果作为两个对象 - 地址和照片。
我想做一个左连接,这样我也可以得到没有照片的人的记录。我已经读过这只能使用 hql 才能实现,但这也可以使用标准来完成吗?
您可以轻松编写 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[] 数组列表。该数组的第一个元素将包含一个对象和第二个元素 - 另一个。
编辑:
如果是左连接,我认为您需要使用本机 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();
这应该适用于您的情况。
基本上,您有两种选择:
从 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();
在 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();
Hibernate 团队终于在 12 年后实现了这样的功能
从休眠文档:
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();
或者您可以使用WITH
和ON
关键字。对那些的评论
重要的区别在于,在生成的 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
你正在寻找的是
(在第一次提出问题并给出了这个答案期间) Hibernate 支持 Theta Join,它允许您执行 1 和 2。但是,只有内部连接可用于 theta 连接样式。
就个人而言,我建议您对适当的关系进行建模,因此您只需要 HQL 中很好支持的 1 和 3。
(另一个答案实际上提供了提供此类功能的新 Hibernate 功能的更新,您可以简单地参考)
最好有一个包含您想要加入的课程的课程,以便将它们放在一起。
但是,如果您只是出于某些偶然目的而加入这些表,则可以使用条件并手动从每个表中加载数据并将它们放在一起。(是的,如果地址和照片有两个单独的类和表,您可以分别拥有这些表的数据)