我正在使用 Hibernate 的 JPA 实现,并且发现性能很差,因为为获取的每个实体发出了多个 SQL 查询。如果我使用联接的 JPA 查询,它只会生成一个 SQL 查询,但不会发现行将为空关系。

例如,考虑这个简单的模式。一个人居住在某个地址并受雇于一家公司。地址和雇主都是可选的,因此可以为空。

@Entity
public  class Person {
    public name;

    @ManyToOne
    @Column(nullable=true)
    public Address address

    @ManyToOne
    @Column(nullable=true)
    public Company employer
}

@Entity
public  class Address {
    address attributes ...
}

@Entity
public  class Company {
    company attributes ...
}

上面没有显示的是每个 JPA 实体都有某种 ID(键):

@Id
public Integer id;

我看到的问题是,对 Person 的单个 JPA 查询会导致对数据库进行多个 SQL 查询。例如,以下 JPA 查询:

select p from Person p where ...

SQL 查询结果:

select ... from Person where ...

以及以下一对 SQL 查询 每个 被找回的人:

select ... from Address a where a.id=xxx
select ... from Company c where c.id=yyy

这对性能有很大影响。如果查询结果集是1000人,那么它会生成1+1000+1000=2001条SQL查询。

所以我尝试通过强制加入来优化 JPA 查询:

select p from Person p join p.address a join p.employer e where ...

或者:

select p, a, e from Person p join p.address a join p.employer e where ...

这会产生一个带有一堆连接的 SQL 查询。问题是如果地址或雇主为空,那么连接的查询将找不到它。

因此,我要么使用速度较慢的无连接查询,要么使用不检索行的快速连接查询将使关系为空。我一定在这里遗漏了一些东西。当然有一种方法可以实现快速、完整的查询。

有帮助吗?

解决方案

我的猜测是你需要一个左连接,即

SELECT p FROM Person p LEFT JOIN p.address a LEFT JOIN p.employer e WHERE...

此博客条目为例

请注意,我实际上并未在 JPA 中尝试过此操作,但它在 HQL 中运行良好,HQL 在很多方面都是 JPA 标准的基础。

它不适用于普通连接的原因是默认是内部连接。

其他提示

尝试在地址和公司实体上设置批量大小 (@BatchSize)。它不会在连接中加载它们(这就是您想要的吗?),但每次加载时它都会加载一堆。批量大小表示当它发现需要时应该加载多少。

如果您的批量大小为 1(默认值),并加载 10 人。然后迭代他们,读取他们的地址和公司项目,然后 hibernate 将为这 10 个人执行一次查询,然后每次它需要其中一个人的地址或公司时,它都会查询该人的地址。

如果您在地址实体上设置了批量大小为 7,那么当您读取第一个地址时,它将看到当前代理的地址超过 7 个,并且会为您获取其中的 7 个地址。

如果您的“地址”和“公司”的 BatchSize 均为 7,并且要迭代 10 个人,那么这将导致 5 次查询,而不是目前的 21 次查询。仍然不是连接会给你的 1。但是,如果您只想要 Person 对象并且不会触及其中嵌入的地址/公司实体(假设您只想获取人员 id 列表,或者计算有多少人),那么连接会变慢。是男/女)

看一下:http://hibernate.org/hib_docs/v3/reference/en/html/performance.html

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top