Hibernate和spring中的session问题整理

查了很多关于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. }  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值