※问题类别: Spring Data JPA
※系统环境: bellsoft-jdk-11.0.14.1
很久没有使用 JPA,最近可能会用到
又回头看了 Spring Data JPA
一开始使用 Spring Boot 练习
第一问题通常会遇到 infinite recursion 的 JsonMappingException
所以使用 Jackson 的各种 annotation 或是转 DTO 来解
因为觉得 Spring Boot 背后做太多事,可能会错过什么
所以改用 Spring 来练习一下
果不其然就发生了 LazyInitializationException - no Session
查了一下,Spring Boot 的 spring.jpa.open-in-view 默认为 true
让 entity 在脱离 transaction scope 时
还能使用 oiv 的 connection 去查 lazy entity 的资料
不过查资料时,是建议关闭这个功能,毕竟拉长占用 connection 的时间
而查到的几种解法
1. 把 @Transactional 设定在操作 lazy entity 的 method
因为 Spring Data JPA 执行流程,会导到 SimpleJpaRepository 来处理
而 SimpleJpaRepository 在 class 上宣告了 @Transactional(readOnly = true)
因为练习的 service 内的 method,可能会查询多次
不希望每个查询都使用一个 read only transaction
所以在 XxxService 的 class 也使用 @Transactional(readOnly = true)
希望多个查询使用同一个 read only transaction
所以我在 XxxService 的 class 上也使用 @Transactional(readOnly = true)
然后在执行 insert, update, delete 的 method 使用 @Transactional
https://imgur.com/2nVTBXH
但如果要使用 @Transactional 来解 no Session 的错误
那就变成要把 @Transactional 设定在 controller 的 method 了
这和 open-in-view 的做法似乎差别不大,只是用同一个 connection 而已?
2. 把 entity 关联设为 FetchType.EAGER
即使没用到,也强制查询关联的 table,应该也不会这样使用
3. Spring Boot 设定 hibernate.enable_lazy_load_no_trans=true
(Spring 的话,在设定 EntityManagerFactory 时,设定 jpa properties)
似乎也是 Hibernate 实做,另开个 Session 查询 lazy entity