Hibernate和spring中的session问题整理

来源:互联网 发布:海洋cms采集插件 编辑:程序博客网 时间:2024/05/17 06:04

查了很多关于spring和hibernate整合的资料,就是想弄懂这个核心问题,这个弄的清楚了,相关的事务问题以及jdbc模板问题也就迎刃而解了。


1.在spring 配置文件中采用如下方式:

<!--spring声明式事务管理--><bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">    <property name="sessionFactory" ref="sessionFactory"/></bean>
那么在实现类中获取session操作
 public class UserDaoImpl implements UserDao { 3    4     private SessionFactory sessionFactory; 5      6     public User findUserById(int id) { 7         Session session = sessionFactory.getCurrentSession(); 8         User user = (User)session.get(User.class, id); 9         session.delete(user);10         11         return user;12     }13 }
使用spring管理事务后在dao中不再需要调用beginTransaction和commit,也不需要调用session.close(),使用sessionFactory.getCurrentSession()来替代sessionFactory.openSession();

对于getCurrentSession():

采用getCurrentSession()创建的session会绑定到当前线程中,而采用openSession()创建的session则不会。

采用getCurrentSession()创建的session在commit或rollback时会自动关闭,而采用openSession()创建的session必须手动关闭。

(1)其所在方法必须进行事务控制
(2)Session在第一次被使用的时候,或者第一次调用getCurrentSession()的时候,其生命周期就开始。然后它被Hibernate绑定到当前线程。当事务结束的时候,不管是提交还是回滚,Hibernate也会把Session从当前线程剥离,并且关闭它。假若你再次调用getCurrentSession(),你会得到一个新的Session,并且开始一个新的工作单元。

对于session.openSession()

这个方法一般在spring与Hibernate的集成中不直接使用,它就是打开一个session,并且这个session与上下文无关,如果对其所在方法进行事务控制,会发现不起作用,原因就是前面提到的,事务控制必须确保是同一个连接,而openSession()打开的session与上下文无关。这个方法与getSession(),getCurrentSession()以及getHibernateTemplate()等方法的区别在于:后面的几个方法spring可以对其进行控制,如果对它们所在的方法进行事务控制,spring可以确保是同一个连接,而openSession()方法,spring无法对其进行控制,所以事务也不会起作用

小结:

(1) 对于getSession(),getSession(false),getCurrentSession()以及getHibernateTemplate()方法而言,如果对其所在方法进行事务控制,那么可以确保在整个方法中只存在一个session,无论你执行了几次CRUD操作,并且所打开的session会在事务结束时自动关闭。

(2) 必须对getCurrentSession()所在的方法进行事务控制(原因见上述分析)

(3) 如果没有对getSession()以及getHibernateTemplate()所在方法进行事务控制,那么如果在方法中进行N次CRUD操作,就会打开N个session,即每次调用getSession()和getHibernateTemplate()方法都会打开新的session。这两个方法的区别在于:getHibernateTemplate()方法结束时会自动关闭连接,而getSession()方法必须手动关闭。

(4) 如果在方法中采用SessionFactory的openSession()方法获得连接进行操作,那么无法对其进行事务控制。

(5) 一般的开发中,通常采用getHibernateTemplate()方法进行数据库操作, getHibernateTemplate()方法采用模板+回调的机制,进行数据库操作很方便,可以查看(其中session的打开与关闭都是在doExecute方法中进行的).

2.当采用hibernateTemplate时,分页也就不像原生的hibernate语句那么方便。这时我们可以采用如下方式来进行分页

  1. public List<Cost> findPage(final int page ,final int pageSize){  
  2.          
  3.         //利用HibernateTemplate.execute()方法,以回调方式使用,不需要关闭session  
  4.         List<Cost> costList = (List)getHibernateTemplate().execute(  
  5.             new HibernateCallback(){  
  6.   
  7.                 @Override  
  8.                 public Object doInHibernate(Session session)  
  9.                         throws HibernateException, SQLException {  
  10.                     // TODO Auto-generated method stub  
  11.                       
  12.                     //使用session对象  
  13.                     String hql= "from Cost";  
  14.                     Query query = session.createQuery(hql);  
  15.                       
  16.                     int begin = (page-1)*pageSize;  
  17.                     query.setFirstResult(begin);  
  18.                     query.setMaxResults(pageSize);  
  19.                       
  20.                     return query.list();  
  21.                 }}      
  22.         );  
  23.           
  24.         return costList;  
  25. }