`

由openSession、getCurrentSession和HibernateDaoSupport浅谈Spring对事物的支持

 
阅读更多

Spring和Hibernate的集成的一个要点就是对事务的支持,openSession、getCurrentSession都是编程式事务(手动设置事务的提交、回滚)中重要的对象,HibernateDaoSupport则提供了更方便的声明式事务支持。

    Hibernate中最重要的就是Session对象的引入,它是对jdbc的深度封装,包括对事务的处理,Session对象通过SessionFactory来管理,openSession和getCurrentSession是管理session的重要的方法。

    openSession和getCurrentSession的根本区别在于有没有绑定当前线程,所以,使用方法有差异:

* openSession没有绑定当前线程,所以,使用完后必须关闭,

* currentSession和当前线程绑定,在事务结束后会自动关闭。

关于事务的边界和传播:

     通常情况下事务的边界需要设置在业务逻辑处理层中,但是,如果在一个业务中涉及到多个业务逻辑层之间的方法,且需要在同一个事务中运行,那么,这就涉及到了事务的传播性。

如果使用openSession,就要在dao层的方法中传递session,而这种做法是很糟糕的,首先增加了参数的个数,另外,方法是否需要事务,完全是可以当做一种独立的服务抽离出的。

因为currentSession是线程级别的,所以,只要业务逻辑方法在同一个线程中,就不会担心上面的问题。这也是currentSession的一个优越处之一。

使用currentSession:

1.在配置文件中将线程配置成Thread级别的。

 

[html] view plaincopy
  1. <span style="font-size:18px"><propertynamepropertyname="hibernate.current_session_context_class">thread</property></span>  

 

2.调用sessionFactory的getCurrentSession方法:

 

[java] view plaincopy
  1. <span style="font-size:18px">publicvoid addUser(User user) {  
  2.   
  3.     Session session = null;  
  4.   
  5.     try {  
  6.   
  7.        session =HibernateUtils.getSessionFactory().getCurrentSession();  
  8.   
  9.        session.beginTransaction();        
  10.   
  11.        session.save(user);          
  12.   
  13.        Loglog = new Log();  
  14.   
  15.        log.setType("操作日志");  
  16.   
  17.        log.setTime(new Date());  
  18.   
  19.        log.setDetail("XXX");        
  20.   
  21.        LogManager logManager = newLogManagerImpl();  
  22.   
  23.        logManager.addLog(log);         
  24.   
  25.        session.getTransaction().commit();  
  26.   
  27.     }catch(Exception e) {  
  28.   
  29.        e.printStackTrace();  
  30.   
  31.        session.getTransaction().rollback();     
  32.   
  33.     }  
  34.   
  35. }</span>  

 

 

使用openSession:

 

[java] view plaincopy
  1. <span style="font-size:18px">public void addUser(User user) {  
  2.   
  3.       Sessionsession = null;  
  4.   
  5.       try{  
  6.   
  7.          session= HibernateUtils.getSession();  
  8.   
  9.          session.beginTransaction();  
  10.   
  11. // 若干操作…………          
  12.   
  13.          session.getTransaction().commit();  
  14.   
  15.       }catch(Exceptione) {  
  16.   
  17.          e.printStackTrace();  
  18.   
  19.          session.getTransaction().rollback();  
  20.   
  21.       }finally{  
  22.   
  23.          HibernateUtils.closeSession(session);  
  24.   
  25.       }  
  26.   
  27.    }  
  28.   
  29.  </span>  

 

使用HibernateDaoSupport声明式事务:

    Spring与Hibernate的集成使用最多的是HibernateDaoSupport,它对session的获取以及事务做了进一步的封装,只需要关注dao的实现,而不用担心某个地方的事务是否关闭。

 

[java] view plaincopy
  1. <span style="font-size:18px">this.getHibernateTemplate().save(user);</span>  

 

关于异常与事务回滚:    

    Spring在遇到运行期异常(继承了RuntimeException)的时候才会回滚,如果是Exception(如用户输入密码错误)抛出就好,事务会继续往下进行。

    Spring对异常的处理的灵活性还是比较高的,可以配置遇到某个Exception进行回滚,某个RuntimeException不回滚,但是对于EJB就没有这么灵活了,EJB相当于是固定的套餐。

不会回滚:   

 

[java] view plaincopy
  1. public void addUser(User user)  
  2.   
  3.    throws Exception {  
  4.   
  5.       this.getHibernateTemplate().save(user);  
  6.   
  7.          //若干操作……            
  8.   
  9.       throw new Exception();  
  10.   
  11.    }  

 

回滚:

 

[java] view plaincopy
  1. public void addUser(User user) {  
  2.   
  3.        this.getHibernateTemplate().save(user);      
  4.   
  5.        //若干操作……         
  6.   
  7.        throw new RuntimeException();  
  8.   
  9.  }  

 

 

Spring与Hibernate的集成,使用HibernateDaoSupport的配置:

   在ssh框架应用中,Spring与Hibernate的事务集成基本上是比较固定的,我们把事务的集成单独配置到applicationContext-common.xml中:

 

[html] view plaincopy
  1. <span style="font-size:18px"><?xml version="1.0"encoding="UTF-8"?>   
  2.   
  3. <beansxmlnsbeansxmlns="http://www.springframework.org/schema/beans"  
  4.   
  5.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  6.   
  7.        xmlns:aop="http://www.springframework.org/schema/aop"  
  8.   
  9.        xmlns:tx="http://www.springframework.org/schema/tx"  
  10.   
  11.         xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.0.xsd  
  12.   
  13.           http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.0.xsd  
  14.   
  15.            http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.0.xsd">  
  16.   
  17.    <!--配置SessionFactory -->  
  18.   
  19.    <beanidbeanid="sessionFactory"class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  
  20.   
  21.       <propertynamepropertyname="configLocation">  
  22.   
  23.          <value>classpath:hibernate.cfg.xml</value>  
  24.   
  25.       </property>  
  26.   
  27.    </bean>  
  28.     
  29.   
  30.    <!--配置事务管理器 -->  
  31.   
  32.    <beanidbeanid="transactionManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
  33.   
  34.       <propertynamepropertyname="sessionFactory">  
  35.   
  36.          <refbeanrefbean="sessionFactory"/>          
  37.   
  38.       </property>  
  39.   
  40.    </bean>  
  41.     
  42.   
  43.    <!--那些类那些方法使用事务 -->  
  44.   
  45.    <aop:config>  
  46.   
  47.       <aop:pointcutidaop:pointcutid="allManagerMethod" expression="execution(*com.bjpowernode.usermgr.manager.*.*(..))"/>  
  48.   
  49.       <aop:advisorpointcut-refaop:advisorpointcut-ref="allManagerMethod" advice-ref="txAdvice"/>  
  50.   
  51.    </aop:config>  
  52.     
  53.   
  54.    <!--事务的传播特性 -->   
  55.   
  56.    <tx:adviceidtx:adviceid="txAdvice" transaction-manager="transactionManager">  
  57.   
  58.       <tx:attributes>  
  59.   
  60.          <tx:methodnametx:methodname="add*" propagation="REQUIRED"/>  
  61.   
  62.          <tx:methodnametx:methodname="del*" propagation="REQUIRED"/>  
  63.   
  64.          <tx:methodnametx:methodname="modify*" propagation="REQUIRED"/>  
  65.   
  66.          <tx:methodnametx:methodname="*" propagation="REQUIRED"read-only="true"/>  
  67.   
  68.       </tx:attributes>  
  69.   
  70.    </tx:advice>  
  71.   
  72. </beans></span>  

 

 

因为在hibernate.cfg.xml中添加了如下配置,所以,在tomcat等容器启动的时候,会自动将相应的bean对象创建。

 

[html] view plaincopy
  1. <span style="font-size:18px"> <propertynamepropertyname="hibernate.hbm2ddl.auto">update</property></span>  

 

applicationContext-beans.xml:

    通常将业务逻辑对实现类的引用单独的xml文件中,同时,在实现类中不能忽略sessionFactory工厂的注入。

 

[html] view plaincopy
  1. <span style="font-size:18px"><?xml version="1.0"encoding="UTF-8"?>   
  2.   
  3. <beansxmlnsbeansxmlns="http://www.springframework.org/schema/beans"  
  4.   
  5.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  6.   
  7.         xmlns:aop="http://www.springframework.org/schema/aop"  
  8.   
  9.        xmlns:tx="http://www.springframework.org/schema/tx"  
  10.   
  11.        xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.0.xsd  
  12.   
  13.            http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.0.xsd  
  14.   
  15.           http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.0.xsd">  
  16.   
  17.             
  18.   
  19.    <beanidbeanid="userManager" class="com.bjpowernode.usermgr.manager.UserManagerImpl">  
  20.   
  21.       <propertynamepropertyname="sessionFactory" ref="sessionFactory"/>  
  22.   
  23.       <propertynamepropertyname="logManager" ref="logManager"/>  
  24.   
  25.    </bean>  
  26.     
  27.   
  28.    <beanidbeanid="logManager"class="com.bjpowernode.usermgr.manager.LogManagerImpl">  
  29.   
  30.       <propertynamepropertyname="sessionFactory" ref="sessionFactory"/>  
  31.   
  32.    </bean>  
  33.   
  34. </beans></span>  

 

事务传播特性:

   为了保证调用的业务逻辑方法都使用同一个事务,通常都使用REQUIRED这个级别,它表示:如果上一个方法中有事务,就直接使用,如果没有,就创建一个事务,这样,一旦事务创建了后,后续调用的方法就不会再创建。

   其他的事务传播特性见下表:


 

Spring事务的隔离级别:

   1. ISOLATION_DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。

        另外四个与JDBC的隔离级别相对应。

   2. ISOLATION_READ_UNCOMMITTED: 这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。

        这种隔离级别会产生脏读,不可重复读和幻像读。

   3. ISOLATION_READ_COMMITTED: 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据

   4. ISOLATION_REPEATABLE_READ: 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。

        它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。

   5. ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。

     除了防止脏读,不可重复读外,还避免了幻像读。

    事务隔离级别主要应用在对大数据的处理方面,与锁的机制是密不可分的,这里不赘述。

分享到:
评论

相关推荐

    getCurrentSession 与 openSession() 的区别

    在Java的Hibernate框架中,`getCurrentSession()` 和 `openSession()` 都是用于获取与数据库交互的Session对象,但它们之间存在显著的区别。理解这些差异对于优化数据访问性能和管理事务至关重要。 首先,`...

    SessionFactory.getCurrentSession与openSession的区别

    理解 `SessionFactory.getCurrentSession()` 和 `Session.openSession()` 的区别对于优化和正确使用Hibernate至关重要。 首先,`SessionFactory` 是Hibernate中的一个接口,它是一个全局的、线程安全的工厂类,用于...

    Spring视频教程(3)

    在这一部分,教程将介绍如何将Struts和Spring整合,包括Web应用的结构配置,以及Spring的ApplicationContext和Struts的ActionServlet如何协同工作,为开发MVC架构的应用提供支持。 7. **JDK动态代理和CGLIB代理的...

    ssh中getCurrentSession的使用

    在Java开发中,SSH通常指的是Struts、Spring和Hibernate这三大框架的集成,它们用于构建企业级Web应用程序。在描述中提到的"ssh中getCurrentSession的使用",实际上可能是指在SSH集成框架中使用Hibernate框架时,...

    Spring4.0+Hibernate4.0+Struts2.3整合案例

    1、Spring 3.x 对 Hibernate 4.x 不提供 HibernateDaoSupport,所以在dao的实现层注入SessionFactory 2、报错:org.hibernate.HibernateException: No Session found for current thread 意思是必须在...

    新Hibernate SessionFactory().getCurrentSession()猫腻

    `getCurrentSession()`方法旨在支持线程绑定的Session管理,它会在合适的上下文中自动打开、关闭或重新连接Session,简化了事务管理和并发控制。 描述中的链接虽然没有提供具体内容,但通常会详细解析`...

    Spring 和Hibernate 整合笔记和jar包

    - **单元测试**:Spring Test和Hibernate Test支持对整合后的应用进行单元测试,如使用JUnit和Mockito。 - **日志配置**:通过log4j或logback进行日志记录,便于调试和问题定位。 综上所述,Spring与Hibernate的...

    spring与hibernate的整合

    在这个例子中,`DepartmentDapImpl` 实现了 IDepartmentDao 接口,`setSessionFactory()` 方法接收由 Spring 容器注入的 SessionFactory 实例。在 `addDepartment()` 方法中,我们通过 SessionFactory 打开 Session...

    spring-orm-hibernate4源码

    通过对Spring-ORM-Hibernate4源码的阅读和研究,我们可以更好地理解这两个框架是如何协同工作的,以及如何优化和定制它们以适应特定的项目需求。这个源码库为开发者提供了一手的学习材料,有助于提升我们在企业级...

    Hibernate编程式事务与Spring Aop的声明式事务(spring与hibernate集成)

    在IT领域,尤其是在Java开发中,事务管理是数据库操作的核心部分,确保数据的一致性和完整性...在实际项目中,根据需求选择适合的事务管理方式,Spring和Hibernate的集成则为Java开发提供了强大且灵活的数据访问支持。

    spring和Nhiberate的集成

    总结来说,Spring.NET和NHibernate的集成使得C#开发者能够充分利用两个框架的优势:Spring.NET提供了优秀的DI和AOP支持,简化了事务管理和对象生命周期管理;而NHibernate则提供了强大的ORM功能,降低了数据库操作的...

    Spring集成Hibernate

    **一、Spring对Hibernate的支持** Spring提供了多种方式来整合Hibernate,包括HibernateTemplate、HibernateDaoSupport以及现在的推荐使用方式:SessionFactoryBean和HibernateJpaVendorAdapter。这些工具和接口...

    hibernate-spring整合

    在Spring中,我们可以使用SessionFactory的openSession()或getCurrentSession()方法获取Session实例。 4. **事务管理**: Spring提供PlatformTransactionManager接口,可以用来管理数据库事务。在Hibernate整合中,...

    Hibernate4Spring3

    在Spring中,我们可以使用`SessionFactory.openSession()`或`SessionFactory.getCurrentSession()`方法获取Session实例。 4. **事务管理**:Spring提供了声明式事务管理,只需在方法上添加@Transactional注解,即可...

    struts2.3.x+spring3.1.x+hibernate3.6 demo

    谷歌百度后,说spring3.1还没有对hibernate4.1开始支持,具体情况不知道,有知道告诉我一下!呵呵 不懂! 我这里有测试的demo 基本上大家能看懂! 还有就是我这里习惯把service和dao按照不同的模块进行划分,比较...

    Spring与Hibernate集成中的session

    - `HibernateTemplate`是Spring提供的一个便捷工具,它封装了`Session`的常用操作,如查询、保存、更新和删除,简化了编码,同时也支持事务管理。 - 使用`HibernateTemplate`可以避免直接操作`Session`,减少可能...

    Struts+Spring+Hibernate开发实例 (SSH整合)

    为此,定义了一个IBase接口和BaseDao实现类,模仿HibernateTemplate的功能,并添加了openSession、getQuery、getCriteria等方法,以处理Spring无法直接支持的场景。然后,为每个实体创建对应的IEntity接口和...

    springmvc+spring3+hibernate4框架整合完整版

    Spring MVC、Spring 3 和 Hibernate 4 是三个在 Java Web 开发中广泛使用的开源框架,它们各自负责不同的职责。Spring MVC 用于构建可扩展的、模块化的Web应用程序,Spring 提供了依赖注入(DI)和面向切面编程(AOP...

Global site tag (gtag.js) - Google Analytics