在Struts2+Spring3+Hibernate4的框架下,本來想在DAO中通過setter注入,給sessionFactory賦值,但是卻出現NullPointerException的異常。經過調試,發現sessionFactory的值為null。后來發現,原來在service層中,這個DAO類的對象是通過new得來的,而不是通過Spring注入的。因此這個new出來的DAO對象,沒有被Spring注入sessionFactory,必然它的sessionFactory為空了。於是改為由Spring提供該對象,成功解決該問題。
其實Spring的意義與好處之一,就是將項目從new的“深淵”中解救出來,用Spring來通過依賴注入,統一提供對象,以實現低耦合(如果不用Spring,那么用工廠模式也可以實現這種效果。但是工廠模式這個對象還是需要new出來,因此沒有Spring的依賴注入那么低耦合)。可是我卻在這里用了new來創建對象,真是大大違背了Spring的主旨。這些代碼是我很久以前寫的,看來我那時候對Spring理解地不夠深入。
另一個問題是,在DAO文件中,通過sessionFactory.getCurrentSession()來獲取會話,報異常:org.hibernate.HibernateException: createQuery is not valid without active transaction。經過實驗,發現將Hibernate的配置文件中的<property name="current_session_context_class">thread</property>屬性去掉就好了。原來"current_session_context_class"屬性的意思是,設置當前會話的上下文環境,如果設置為thread,那么同一線程則共享同一session會話。因此通過getCurrentSession()得到的session,是同一線程上的session,而不是Spring管理的那個能夠自動開啟事務的session。去除掉該屬性就好了。
發現一些書上和網上均說明,如果要使用getCurrentSession(),必須在Hibernate的配置文件中加上<property name="current_session_context_class">thread</property>這個屬性。我就是按照他們說的做的,結果卻有問題。看來盡信書不如無書,別人一致認可的結論也不一定是正確的,在某些情況下可能是錯的。