(转载)Spring 3.x 和 Hibernate4.x 整合时遇到的No Session found for current thread问题的解决办法
大家都知道,Hibernate升级到4.x以后,在Spring中,通过Hibernate访问数据库的方法已经发生了变化,不再是以往让自己的DAO实现类继承HibernateDAOSupport,然后使用getHibernateTemplate()方法,操作数据库。新的模式下,只能通过从Spring注入的SessionFactory,使用Hibernate原生的方法,操作数据库。
在Spring配置文件中,配置DAO实现类的时候,已经将sessionFactory注入到了DAO实现类中,代码如下:
<bean id="dao" class="j.CatDAOImpl"> <property name="sessionFactory" ref="sessionFactory"/> </bean>
我们需要在我们的DAO实现类中,定义一个同名的属性,来接收注入的sessionFactory。
public class CatDAOImpl implements ICatDAO { private SessionFactory sessionFactory;
并设置其setter和getter方法。
完成DAO操作时,即可以使用如下代码完成
public void createCat(Cat c) { // TODO Auto-generated method stub Session session=sessionFactory.getCurrentSession(); session.persist(c); }
获得Session以后,操作数据库的方法和Hibernate完全一致。
但是,问题来了!写好以上程序,执行时,会报如下错误。
nested exception is org.hibernate.HibernateException: No Session found for current thread
查了一下相关资料,才知道,原来要Hibernate中使用Session,需要在配置文件中申明事务。这种申明式事务的好处是,把事务的管理完全从业务程序中分离出来,作为一个可配置、可插拔的功能。程序中不再需要任何管理事务的代码,既可以完全实现事务处理的功能。这一点也正是体现了Spring面向方面编程的优越性。
要配置事务支持,需要在Spring配置文件中配置如下内容
<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- 使用annotation声明 --> <tx:annotation-driven /> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="get*" read-only="true" propagation="REQUIRED" /> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="*" propagation="REQUIRED" /> </tx:attributes> </tx:advice>
同时,在获得Session的DAO实现类的方法上,要添加@Transactional("txManager")标注。代码如下:
@Transactional("txManager") @Override public void createCat(Cat c) { // TODO Auto-generated method stub Session session=sessionFactory.getCurrentSession(); session.persist(c);