虽然hibernate里好几种fetch mode.
- SELECT
- SELECT with BatchSize
- JOIN
- SUBSELCT
但是JPA里只有两种类型的fetching:EAGER
和LAZY
。在使用spring data jpa的时候,为了解决n+1查询问题,我们需要在查询中手动的控制fetch mode。
1 | public void testPagedSpecificationProjection() { |
第四行判断了返回类型是否为Long,是因为分页查询时spring data会先执行一次count查询,此时关联对count查询是没有意义的,会一个抛异常:
org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list
如果不是分页查询,则不需要判断返回类型。
顺带一提,关于jpa里的@OneToOne关联,如果关联的表允许为空,即optional=true
,那么fetch = FetchType.LAZY
是不起作用的,具体的解释参考:SomeExplanationsOnLazyLoadingone-to-one。@OneToOne
的双向关联一定要慎用,一不小心就会造成n+1查询问题。
参考:https://jira.spring.io/browse/DATAJPA-105
http://jdpgrailsdev.github.io/blog/2014/09/09/spring_data_hibernate_join.html