Java JPA中显式连接和隐式连接的区别是什么?(表演)
这些天我在读有关JPA的文章。我了解到在JPQL中可以使用Java JPA中显式连接和隐式连接的区别是什么?(表演),java,jpa,jpa-2.0,jpql,Java,Jpa,Jpa 2.0,Jpql,这些天我在读有关JPA的文章。我了解到在JPQL中可以使用显式或隐式连接 显式联接 em.createQuery(“从书b中选择b.title、p.name加入b.publisher p”).getResultList() 隐式联接 em.createQuery(“从书中选择b.title、b.publisher.name b“.getResultList() 这些例子的来源: 我的问题是:在显式和隐式连接之间的性能有什么区别吗 更新 我已经读了你写的@MatteoBaldi和@Kayaman
显式
或隐式
连接
显式联接
em.createQuery(“从书b中选择b.title、p.name加入b.publisher
p”).getResultList()
隐式联接
em.createQuery(“从书中选择b.title、b.publisher.name
b“.getResultList()
这些例子的来源:
我的问题是:在显式
和隐式
连接之间的性能有什么区别吗
更新 我已经读了你写的@MatteoBaldi和@Kayaman,我做了一些测试,我想和你分享结果 我创建了两个实体:
学生
和课程
,我有一个多个
(许多学生参加一个课程)。我使用了EcpliseLink
实现JPA
查询=从课程、执行场景中选择学生和DummyField:
因此,在我的测试环境(EclipseLink,…)中,我拥有从JPQL查询生成的相同SQL查询。因此,我可以说,性能将是相同的(当然,在我的测试条件中,我再次指出,我希望有人能够确认/纠正我的结果,并制定一个一般规则。它们应该是相同的,但实际上主要取决于底层数据库。在当前环境中测试性能的一个快速方法是启用SQL日志记录,跟踪您的
jpql的本机查询代码>被传输到SQL客户机中并直接使用SQL客户机进行尝试。它们的解析方式不同,因此根据查询、实体关系和其他类似的内容,它们最终可能会成为不同的SQL查询。理想情况下,只要JPQL查询执行相同的操作,就应该没有区别,但是
推荐的方法是使用显式连接,这还有其他优点,例如在惰性关系上指定连接获取
。这个问题过于关注性能,显然,如果其中一个性能更好,但结果相同,那么就没有理由使用较慢的连接
启用SQL日志记录以查看生成的查询是验证应用程序是否正在执行您期望的查询的一个好方法,无论您使用何种语法。您不能仅仅依赖JPQL,您需要了解和理解您的数据库,因此您不只是使用“模糊层”作为“没有名字的马”来调用ORM框架;)通常,我总是显式地显示每个连接。主要目标是更清楚地了解查询在做什么,以及如何进行查询,从而获得一个更可预测的SQL,以及查询的未来更改
但是我可以给你一个例子,隐式连接比显式连接有更高的性能,即使在大多数情况下,这种性能增益也非常小,而且就个人而言,不会承担风险(我将在后面解释什么样的风险)
假设您正试图将所有书籍与同一出版商分组。使用explicitJOIN,这就是JPQL:
SELECT count(publisher.id)
FROM FROM Book b
JOIN b.publisher publisher
WHERE publisher.id = 1
GROUP by publisher.id
此查询是可读的,没有任何重复,并且此查询中的任何更改(如添加另一个WHERE
条件)将按预期维护生成的SQL
现在,使用隐式连接:
SELECT count(b.publisher.id)
FROM FROM Book b
WHERE b.publisher.id = 1
GROUP by b.publisher.id
b.publisher.id的重复了三次。如果您添加另一个条件,则Hibernate的JPQ解释可能会更改生成的SQL,从而执行不必要的联接,如上所述
但是这个带有隐式连接的JPQL不会对生成的SQL执行额外的JOIN
到publisher
表,因为他可以使用published\u id
中的id
:
SELECT Count(b.published_id) AS col_0_0_
FROM Book b
WHERE b.published_id = ?
GROUP BY b.published_id
以及SQL显式连接和额外的连接
:
SELECT Count(published.id) AS col_0_0_
FROM Book b
INNER JOIN published published1_
ON b.published_id = published1_.id
WHERE published_id = ?
GROUP BY published_id
但是,只有当来自publisher
的外键位于book
端时,才会发生这种情况。在这种情况下,这是正确的方法,但是存在一些映射,其中外键可以位于表的任意端,因此显式和隐式JPQLs查询可以生成相同的SQL
根据我的经验,显式连接总是一个更好的选择。Hibernate并不总是理解在同一个查询上重复的同一个隐式连接是同一个连接的一部分,从而创建了未优化/奇怪的SQL。为什么它会依赖于数据库?如果JPA将它们都解析到同一个查询中,则没有区别。因此问题是,JPA是否总是将它们解析为同一个查询。因为您的JPA实现使用您定义的SQL方言来翻译这些查询。该方言仍然是JPA实现的一部分,而不是数据库。该方言通常对JPQL也没有太多的说明。将查询翻译为特定于数据库的语法,此时连接等的一般结构应该已经完成。您是说相同的jpql查询在Oracle数据库和MySQL数据库上具有相同的性能(仅以这些为例)?如果需要比较性能,则必须获取本机查询并在现场进行尝试。当然不是,我们不是在比较不同的数据库。我们是在比较这两个JPQL查询以及它们是否最终成为相同的SQL查询。这取决于JPA实现。如果您查看内容