gpt4 book ai didi

database - OneToMany(fetch=FetchType.EAGER) 是否执行 N+1 个查询

转载 作者:行者123 更新时间:2023-12-02 09:47:18 24 4
gpt4 key购买 nike

我正在使用 spring boot、spring data 和 Hibernate 开发一个应用程序。我有一个实体“客户”,该实体与另一个实体“预订”有“onetomany”关系,如下所示:

@Entity
public class Client implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@OneToMany( mappedBy = "client", fetch=FetchType.EAGER)
@Fetch(value = FetchMode.JOIN)
private Set<Reservation> reservations = new HashSet<>();
}

我已经实现了 JpaRepository 接口(interface),所以我可以操作客户端数据:
public interface ClientRepository extends JpaRepository<Client, Long> {}

在一个服务类中,我实现了一种在我的数据库中查找所有客户端的方法:
@Service
public class ClientService {

@Autowired
private ClientRepository clientRepository;

@Transactional(readOnly = true)
public List<Client> findAll() {

return clientRepository.findAll();
}}

findAll() 的执行运行良好并返回所有客户及其预订。但是,在我的 sql 日志中,我已经执行了 N+1 个查询(N 个客户端数),尽管我已经设置了 fetch=FetchType.EAGER在我的客户实体中。我认为 hibernate 将创建一个查询,在该查询中它连接所有必要的数据以检索客户及其预订。

因此,我被迫通过查询显式加入客户端和预订:
    @Query("select client from Client client left join fetch client.reservations")
public List<Client> findAllEager();

我还找到了另一种选择,它只允许执行两个查询来检索所有客户及其预订:
    @OneToMany(mappedBy = "client", fetch = FetchType.EAGER)
@Fetch(value = FetchMode.SUBSELECT)

我注意到从这个讨论 JPA eager fetch does not join ,看来 @OneToMany(fetch=FetchType.EAGER) @Fetch(value = FetchMode.JOIN)将只执行一个查询来检索结果,这不是我的情况。

是否 OneToMany(fetch=FetchType.EAGER)执行 N+1 个查询来获取数据?

最佳答案

@OneToMany(fetch=FetchType.EAGER)仅定义 获取相关实体,它没有定义如何实体被获取。 (即它们是由单个连接的 SQL 还是多个分离的 SQL 获取的),因此它可以执行 N+1 个查询。
@Fetch(value = FetchMode.JOIN)定义如何获取相关实体但是,它仅在使用 ID 直接获取实体时有效(即通过 entityManager.find(Client.class, 100) 但对 JPQL 查询或 Criteria API 没有影响。(正如 Hibernate 用户指南所说的 below ) :

The reason why we are not using a JPQL query to fetch multiple Department entities is because the FetchMode.JOIN strategy would be overridden by the query fetching directive.

To fetch multiple relationships with a JPQL query, the JOIN FETCH directive must be used instead.

Therefore, FetchMode.JOIN is useful for when entities are fetched directly, via their identifier or natural-id.



Spring 数据内部使用 findAll() 的 Criteria API查询,所以 @Fetch(value = FetchMode.JOIN)不会有任何影响。您必须明确使用 JOIN FETCH查询以避免 N+1 个查询。

关于database - OneToMany(fetch=FetchType.EAGER) 是否执行 N+1 个查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53938827/

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