我就是奇迹

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

在 JPA(Java Persistence API)中确实存在 Lazy Loading(懒加载)与 N+1 查询问题,这两个概念往往是一起讨论的,因为懒加载是 N+1 问题的主要诱因之一。

 


 

✅ 什么是 Lazy Loading(懒加载)?

 

在 JPA 中,当你使用 @OneToMany、@ManyToOne 等关联关系时,可以指定加载策略:

FetchType.LAZY:懒加载,表示当你首次访问该关联属性时,才会从数据库查询数据。

FetchType.EAGER:立即加载,表示在主实体加载时,关联实体也立刻加载。

 

懒加载的好处是节省性能,但也容易带来 N+1 查询问题

 


 

❌ 什么是 N+1 查询问题?

 

假设你有一个实体 User,每个用户关联一个 Department(部门)。你写了一条查询,加载了 10 个用户:

List<User> users = userRepository.findAll(); // 一次查询

然后你访问每个用户的部门:

for (User user : users) {
    System.out.println(user.getDepartment().getName()); // 每次访问都触发一次查询
}

结果是:

第一次查询 users:1 次

每个 user.getDepartment() 触发懒加载:10 次

 

👉 总共执行了 1 + 10 = 11 次查询,这就是 N+1 查询问题!

 


 

🔧 如何解决 N+1 查询问题?

1. 使用 Fetch Join:

在 JPQL/HQL 中显式使用 join fetch:

@Query("SELECT u FROM User u JOIN FETCH u.department")
List<User> findAllWithDepartment();

 

2. 使用 EntityGraph:

@EntityGraph(attributePaths = "department")
List<User> findAll();

 

3. 适当使用 EAGER,但小心内存开销和无限递归问题。

4. Hibernate 的 Batch Fetching:

配置 hibernate.default_batch_fetch_size,让懒加载时批量加载多个对象,减少 SQL 次数。

 


 

🧠 总结一句话:

 

懒加载本身并不是问题,但如果你没有控制好访问时机和批量加载策略,就可能导致 N+1 查询问题,严重影响性能。
posted on 2025-04-04 20:43  我就是奇迹  阅读(38)  评论(0)    收藏  举报