Session获取不到的情况及解决办法(源码解析)
本博客是自己在学习和工作途中的积累与总结,欢迎大家转载,转载时请注明出处,请尊重他人努力成果,谢谢。
1. 当有连个sessionFactory时,容易产生获取不到session的情况
原因: 进入事务@Service标注的业务类的业务方法后,当进行数据库操作时,会通过sessonFactory.getCurrentSession();方法获取,原理,当本地线程中不存在session时,会调用openSession创建一个并绑定到本地线程中,然后调用,注意:这里的创建是当前事务该类中事务所绑定的sessionFactory的session,所以在同一方法中的后N个sessionFactory获取session时,只要他们的sessionFactory与当前事务所配置的sessionFactory不是同一个,会报获取不到session的异常,因为该session获取不到。或者更详细地说,由于spring维护一个ThreadLocal<Thread,Map<Object,Object>>来解决线程安全问题,那么,以当前线程作为key值,取到存有当前线程中的所需的键值对map,而其中就拥有sessionFactory和SessionHolder的键值对,而key值SessionFactory对象即为当前事务的sessionFactory,所以如果是其他sessionFactory去获取的话,会导致拿取出来的值为null。
补充一下:sessionHolder就是拿去session的对象哦 ,在CurrentSessionContext的接口实现类中的currentSession方法中。
解决办法:
1. 常用的sessionFactory的事务管理可以使用注解配置 ,不常用的可以使用spring的声明式事务管理配置(可以配置多个),这样就互不相干,不会出现拿不到sesson的问题
2. 后续的sessionFactory需要自己手动的调用openSession,来进行操作,并且需要手动关闭。
补充一下,使用懒加载也会导致拿不到session,但于此问题无关,可以配置open session in view,但会极其损耗应用性能。
源码解析:
此中,resources.get()方法是为了拿去当前线程中的所有键值对,而sessionFactory的实例对象在此map中为键,值为SessionHolder实例对象(org.springframework.orm.hibernate4.SessionHolder),
而唯有事物中配置的sessionFactory才能通过map取出value(SessionHolder对象),所以返回null。
接下来:
返回null
由于value=null,所以抛一个异常喽