JPA(Hibernate)延迟加载相关
问题描述
org.hibernate.LazyInitializationException - no session
原因:查询数据库事务已经关闭,再去调用其内部属性时没有session(这里说的是数据库session,不是web session)
Spring框架中的数据库事务
已知解决方案
1、关闭LazyInitialization, 将fetch设成eager,可以在配置文件,也可注解
2、在spring boot的配置文件application.properties添加
spring.jpa.open-in-view=true
不建议使用 原因 -> What is this spring.jpa.open-in-view=true property in Spring Boot?
3、用spring 的OpenSessionInViewFilter,实现原理类似2
4、在spring boot的配置文件application.properties添加
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
5、在实体类上加@Proxy(lazy = false),
if you are using XML configuration: add default-lazy="false" to your element
if you are using annotation configuration: add @Proxy(lazy=false) to all your entity classes.
6、2. 通过在查询中使用 fetch 的方式
通过再查询中使用 fetch,一次将相关数据查询出来,不会产生 N + 1 的影响。
继续使用上面的 用户-权限 的例子。先把 spring.jpa.properties.hibernate.enable_lazy_load_no_trans 这个配置去掉,然后在UserRepository 中添加如下方法:
@Query("from User u join fetch u.authorityList")
public User findOne(Long id);
测试类中的 queryUser 代码改为下面的:
@Test
public void queryUser() {
User user = userRepository.findOne(2L);
System.out.println(user);
System.out.println(user.getAuthorityList());
}
进行查询,只会执行一条sql:
Hibernate: select user0_.id as id1_5_0_, authority2_.id as id1_3_1_,
user0_.password as password2_5_0_, user0_.username as username3_5_0_,
authority2_.name as name2_3_1_, authorityl1_.user_id as user_id1_6_0__,
authorityl1_.authority_id as authorit2_6_0__
from user user0_
inner join user_authority authorityl1_ on user0_.id=authorityl1_.user_id
inner join authority authority2_ on authorityl1_.authority_id=authority2_.id
通过 sql 可以看出,实际上就是使用了sql 里的 join 一次查询出来多条数据。
原文链接