gpt4 book ai didi

java - JPA 急切未加入

转载 作者:IT老高 更新时间:2023-10-28 11:24:30 25 4
gpt4 key购买 nike

JPA 的 fetch 策略究竟控制什么?我无法发现急切和懒惰之间的任何区别。在这两种情况下,JPA/Hibernate 都不会自动加入多对一关系。

示例:人只有一个地址。一个地址可以属于很多人。 JPA 注释的实体类如下所示:

@Entity
public class Person {
@Id
public Integer id;

public String name;

@ManyToOne(fetch=FetchType.LAZY or EAGER)
public Address address;
}

@Entity
public class Address {
@Id
public Integer id;

public String name;
}

如果我使用 JPA 查询:

select p from Person p where ...

JPA/Hibernate 生成一个 SQL 查询以从 Person 表中进行选择,然后为 每个 人生成一个不同的地址查询:

select ... from Person where ...
select ... from Address where id=1
select ... from Address where id=2
select ... from Address where id=3

这对于大型结果集非常不利。如果有 1000 人,它会生成 1001 个查询(1 个来自 Person,1000 个来自 Address)。我知道这一点是因为我正在查看 MySQL 的查询日志。我的理解是,将地址的获取类型设置为 eager 会导致 JPA/Hibernate 自动使用连接进行查询。但是,无论获取类型如何,它仍然会为关系生成不同的查询。

只有当我明确告诉它加入时,它才会真正加入:

select p, a from Person p left join p.address a where ...

我在这里遗漏了什么吗?我现在必须手动编写每个查询的代码,以便它离开多对一关系。我在 MySQL 中使用 Hibernate 的 JPA 实现。

编辑:看来(参见 Hibernate FAQ herehere)FetchType 不会影响 JPA 查询。所以就我而言,我已经明确告诉它加入。

最佳答案

JPA 没有提供任何关于映射注释以选择获取策略的规范。通常,可以通过以下任何一种方式获取相关实体

  • SELECT => 一次查询根实体 + 一次查询相关映射实体/每个根实体的集合 = (n+1) 次查询
  • SUBSELECT => 一个查询根实体 + 第二个查询相关映射实体/在第一个查询中检索到的所有根实体的集合 = 2 个查询
  • JOIN => 一个查询来获取根实体及其所有映射实体/集合 = 1 个查询

所以 SELECTJOIN 是两个极端,而 SUBSELECT 介于两者之间。可以根据自己的领域模型选择合适的策略。

默认情况下,JPA/EclipseLink 和 Hibernate 都使用 SELECT。这可以通过使用覆盖:

@Fetch(FetchMode.JOIN) 
@Fetch(FetchMode.SUBSELECT)

处于 hibernate 状态。它还允许使用 @Fetch(FetchMode.SELECT) 显式设置 SELECT 模式,该模式可以通过使用批量大小进行调整,例如@BatchSize(size=10).

EclipseLink中对应的注解有:

@JoinFetch
@BatchFetch

关于java - JPA 急切未加入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/463349/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com