springboot jpa getOne方法遇到延迟加载报错no Session的问题

博客主要讲述调用JPA预生成方法getOne时提示异常,原因是遇到延迟加载且session关闭。给出三种解决办法:一是在调用方法层级添加事务@Transactional;二是在Properties添加配置,但此方式不友好;三是用findById替代getOne,并提醒findById返回Optional。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在调用jpa的预生成方法getOne提示异常
org.hibernate.LazyInitializationException:
could not initialize proxy [com.cashbook.trunk.business.tally.domain.Tally#28] - no Session
原因:遇到延迟加载,session关闭了,导致不能得到有效信息

解决1:
在调用该方法的层级添加事务@Transactional(感谢BigBigChris的指点)

解决2:
Properties添加spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
但是该方式不太友好,不建议使用,每次初始化一个实体的关联就会创建一个临时的session来加载,每个临时的session都会获取一个临时的数据库连接,开启一个新的事物。这就导致对底层连接池压力很大,而且事物日志也会被每次flush.

解决3:
使用findById来替代getOne(注意,findById返回的是Optional)
ps:
Tally tally = tallyRepository.findById((long) 99).orElse(null);//使用orElseGet时对象为空会报异常

在多线程环境下,JPA的懒加载会出现No Session错误,原因是每个线程都有自己的session,而懒加载是在session中进行的,当线程切换时,session也会切换,导致当前线程没有session而无法进行懒加载操作。 解决方案就是在每个线程中手动维护session,可以使用ThreadLocal来存储当前线程的session对象,保证每个线程都有自己的session,并且在使用完后及时关闭session。 以下是一个简单的示例代码,使用了SpringBootJPA,其中使用了ThreadLocal来存储session对象: ``` @Service public class UserService { @Autowired private UserRepository userRepository; private static final ThreadLocal<Session> sessionThreadLocal = new ThreadLocal<>(); public void doSomethingInNewThread() { new Thread(() -> { Session session = getSession(); User user = userRepository.findById(1L).orElse(null); if (user != null) { // 使用session进行懒加载操作 Hibernate.initialize(user.getOrders()); } closeSession(); }).start(); } private void closeSession() { Session session = sessionThreadLocal.get(); if (session != null) { session.close(); sessionThreadLocal.remove(); } } private Session getSession() { Session session = sessionThreadLocal.get(); if (session == null) { session = entityManager.unwrap(Session.class); sessionThreadLocal.set(session); } return session; } } ``` 在上面的代码中,我们在doSomethingInNewThread方法中创建了一个新的线程,并在其中使用ThreadLocal来存储当前线程的session对象。在使用完后,我们及时关闭session并从ThreadLocal中移除它。 需要注意的是,我们需要使用entityManager来获取当前线程的session对象,并且在使用完后需要手动关闭session。同时,我们在使用session进行懒加载操作时,需要使用Hibernate.initialize来强制进行加载。 希望这个示例代码能够帮助你解决懒加载No Session问题
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值