多线程与hibernate session

1、关于SessionFactory和Session

  SessionFactory的实现是线程安全的,多个并发的线程可以同时访问一 个SessionFactory并从中获取Session实例,而Session不是线程安全的。Session中包含了数 据库操作相关的状态信息,那么说如果多个线程同时使用一个Session实例进行CRUD,就很有可能导致数据存取的混乱。每个线程/事务应该从一个SessionFactory获取自己的session实例,才能在新线程中使用事务和延迟加载等功能,否则会曝出no session异常。

 解决办法:
[java] view plain copy
  1. new Runnable() {  
  2.                 @Override  
  3.                 public void run() {  
  4. //                  ----------绑定session到当前线程------------  
  5.                     SessionFactory sessionFactory = (SessionFactory)applicationContext.getBean("sessionFactory");  
  6.                     boolean participate = ConcurrentUtil.bindHibernateSessionToThread(sessionFactory);  
  7. //                  ---------你的业务---------------  
  8. <pre name="code" class="java">//                  ----------关闭session------------                     
  9.                     ConcurrentUtil.closeHibernateSessionFromThread(participate, sessionFactory);  
  10.                 }  
  11.                   
  12.             }  

其中applicationContext.getBean("xxx"),可能涉及到多线程的spring注解注入问题

 
 bindHibernateSessionToThread方法: 
 
[java] view plain copy
  1. public static boolean bindHibernateSessionToThread(SessionFactory sessionFactory) {  
  2.     if (TransactionSynchronizationManager.hasResource(sessionFactory)) {  
  3.         // Do not modify the Session: just set the participate flag.  
  4.         return true;  
  5.     } else {  
  6.         Session session = sessionFactory.openSession();  
  7.         session.setFlushMode(FlushMode.MANUAL);  
  8.         SessionHolder sessionHolder = new SessionHolder(session);  
  9.         TransactionSynchronizationManager.bindResource(sessionFactory, sessionHolder);  
  10.     }  
  11.     return false;  
  12. }  
closeHibernateSessionFromThread方法
[java] view plain copy
  1. public static void closeHibernateSessionFromThread(boolean participate, Object sessionFactory) {  
  2.   
  3.     if (!participate) {  
  4.         SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.unbindResource(sessionFactory);  
  5.         SessionFactoryUtils.closeSession(sessionHolder.getSession());  
  6.     }  
  7. }  

事务边界则由aop或者Transactional标记来控制,示例代码只是保证具备事务性的方法在需要的时候能从当前线程中获得session对象。

上述代码大部分截取自Spring的OpenSessionInViewFilter。

2、session的创建:

 

  Hibernate中的Session通过SessionFactory来创建,具体的创建方式有两种:

  SessionFactory.getCurrentSession()、SessionFactory.openSession() ;

  这两种创建Session的方式主要有如下差别:

  a:getCurrentSession创建的session会绑定到当前线程,而openSession不会。

  b:getCurrentSession创建的线程会再事务回滚或事务提交后自动关闭,而openSession必须手动关闭

  c:getCurrentsession需要在hibernate.cfg.xml文件中添加配置:                                      <propertyname="current_session_context_class">thread</property>


3、spring hibernate session

使用hibernate进行数据库操作时,需要session,并且需要对sesssion进行事务管理.

当使用spring来集成hibernate时,spring会帮我们管理session的事务,因此无需我们手动操作事务(提交、回滚等)。

在Spring托管中,session并不是程序员自己控制的,session的生命周期交由Spring管理。影响session生命周期的情况有这几种:

  1. 使用SessionFactory.getCurrentSession()方法。

  2. 使用HibernateTemplate来屏蔽对session的直接访问。

  3. 使用HibernateTransactionManager,并在session使用区域外围包装了本地事务,甚至是事务嵌套。

  4. 使用了JtaTransactionManager,并在session使用区域外围包装了Jta事务,甚至是事务嵌套。

  5. 使用了OpenSessionInViewFilter。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值