问题描述
今天学习SpringBoot,在随课写代码的时候遭遇一个异常:
org.hibernate.LazyInitializationException: could not initialize proxy [com.law.Entity.ProductCategory#1] - no Session
我感觉下面的信息都不关键,这句大概就够了。贴一下完整代码,万一有用呢:
实体类:
@Entity
public class ProductCategory {
//Category ID
@Id
@GeneratedValue
private Integer categoryId;
//Category Name
private String categoryName;
//Category Type Number
private Integer categoryType;
//此处省略getter、setter和一个toString方法
}
Repository接口 和 测试类:
public interface ProductCategoryRepository extends JpaRepository<ProductCategory, Integer> {
}
@RunWith(SpringRunner.class)
@SpringBootTest
public class ProductCategoryRepositoryTest {
@Autowired
private ProductCategoryRepository productCategoryRepository;
@Test
public void findOneTest(){
ProductCategory productCategory = productCategoryRepository.getOne(1);
System.out.println(productCategory);
}
}
错误原因:
一开始怀疑是版本问题,因为我的idea在创建工程时只能使用2.x版本,我懒得去处理,于是就创建了2.x。但是后来我对比了之前运行成功过的SpringBoot项目,发现代码上没有什么差异,于是暂时排除了这一可能,但实际上还没有弄得特别明白。
后来在别的地方看到了转载自未知出处(并没有原文链接所以并不知道原文在哪里,至于是在哪看到的,忘了=,=)的一段文字:
因为 hibernate(这里是 Spring Data JPA ) 跟 spring 整合以后
hibernate 的 session 就交给 spring 管理了
请求进来的时候打开 session,请求完成的时候关闭 session
当我们想要使用懒加载去获取数据的时候
这时候原先的那个 session 已经关闭了
不能再获取数据了。
解决方案
网上有很多关于这个问题的解法,但是我看了很多问题都是出在有@OneToMany或相关注解的地方。
最终在我这里成功解决问题的有两种方法
第一种受启发于 这里
在配置文件中添加如下项:
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
大致明白意义是启动延迟加载,加上这个配置后可以正常输出结果。但是正如上面链接里提到的,这个方法在项目需要移植时可能会失效。
第二种
这是病入膏肓的时候突然想到的,大概是很早看到的某篇文章提到,如果子类如何如何,出现这种问题,那么需要为父类添加@Transactional注解。我想想我这也没有父类,于是我给测试方法加上了@Transactional注解,同样能解决问题。
网上还有第三种解决方法,但是我这里运行一就报错
在配置文件中添加
spring.jpa.open-in-view=true
并没有解决问题……
总结
平常也不爱把笔记之类的发到CSDN上,这是第一次,希望做一个新尝试,如果不能有很好的效果就算了hhhh,希望各位大佬轻点下手。
我其实并不知道其中的原理具体是什么,今天就到此休息,明天再继续研究是怎么回事,如果有幸有大佬看到了,希望大佬能指出我的错误,并给出您的见解。
其实我还是很怀疑是不是版本的问题,但是我印象中我之前自己摸索着做的SpringBoot小工程没有出现过这些问题,代码中也没有添加注解,设置中也没有上述方法1中的配置。希望有懂的人能分享一下。