本博客是自己在學習和工作途中的積累與總結,歡迎大家轉載,轉載時請注明出處,請尊重他人努力成果,謝謝。
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,所以拋一個異常嘍