且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

JPA休眠n + 1问题(懒惰和渴望差异)

更新时间:2022-06-25 09:34:27

问题"并不是真正的问题,它与ORM的工作方式有关. Hibernate创建所谓的嵌套查询(如果您访问这样的关联).

The "issue" is not really an issue, it's about how ORMs work. Hibernate creates so called nested queries if you access an association like that.

您是正确的,在两种情况下都执行相同的查询,将映射的FetchTypeLAZY切换到EAGER仅是安排执行其他(n + 1)个查询.

You are right, in both cases the same queries are executed, switching the FetchType of your mapping from LAZY to EAGER is only scheduling the execution of the additional (n+1) queries.

假设您有很多公司,所有公司都有雇员,在两种情况下都执行了这样的查询(至少一次):

Assume you have many companies, all of them have employees, in both cases queries like that are executed (at least once):

select ... from company company0_

select ... from employee employee0_ where employee0_.cmp_id=?

执行第一个命令以获取所有公司,第二个为每个公司执行一次.

The first one is executed to get all companies, the second one for every company once.

例如:3个拥有很多员工的公司(N)将执行一次第一次选择,而三个嵌套选择= 3 + 1 = 4个查询之和.

E.g.: 3 companies (N) with many employees will execute the first select once and three nested selects = 3+1 = 4 queries in sum.

EAGERLAZY之间的区别仅在于时间点,通常无法避免数据库访问,因为您仍然需要数据.使用LAZY,附加查询将被推迟,直到您迭代员工集合为止.但是请记住,这只是一个提示,并非每个数据库驱动程序都支持延迟加载.

The difference between the EAGER and LAZY is just about the point in time, you can't avoid database access in general because you nevertheless need the data. With LAZY the additional query is just postponed until you iterate the employee collection(s). But keep in mind that it's just a hint, not every database driver is supporting lazy loading.

如果您真的知道自己始终需要数据,可以编写一个FETCH JOIN查询并一次性接收所有需要的数据:

If you really know that you always need the data you can write a FETCH JOIN query and receive all needed data in one shot:

Select c from Company c JOIN FETCH c.employee e

这将执行如下查询:

select ... from company company0_ inner join employee employee1_ on company0_.cmp_id=employee1_.cmp_id

这将避免第二次数据库访问.为了验证您的测试,也许数据源代理项目为你.

That will avoid the second database access. To verify that in your tests, maybe the datasource proxy project is something for you.