spring声明式事务解析

一、spring声明式事务

1.1 spring的事务管理器

spring没有直接管理事务,而是将管理事务的责任委托给JTA或相应的持久性机制所提供的某个特定平台的事务实现。spring容器负责事物的操作,spring容器充当切面,事务的方法称为增强处理,生成的代理对象的方法就是目标方法+增强也就是crud+事务程序员只用做crud的操作,也就是目标方法和声明哪些方法应该在事务中运行。

Spring提供了许多内置事务管理器实现:

DataSourceTransactionManager:位于org.springframework.jdbc.datasource包中,数据源事务管理器,提供对单个javax.sql.DataSource事务管理,用于Spring JDBC抽象框架、iBATIS或MyBatis框架的事务管理;
JdoTransactionManager:位于org.springframework.orm.jdo包中,提供对单个javax.jdo.PersistenceManagerFactory事务管理,用于集成JDO框架时的事务管理;
JpaTransactionManager:位于org.springframework.orm.jpa包中,提供对单个javax.persistence.EntityManagerFactory事务支持,用于集成JPA实现框架时的事务管理;
HibernateTransactionManager:位于org.springframework.orm.hibernate3包中,提供对单个org.hibernate.SessionFactory事务支持,用于集成Hibernate框架时的事务管理;该事务管理器只支持Hibernate3+版本,且Spring3.0+版本只支持Hibernate 3.2+版本;
JtaTransactionManager:位于org.springframework.transaction.jta包中,提供对分布式事务管理的支持,并将事务管理委托给Java EE应用服务器事务管理器;
OC4JjtaTransactionManager:位于org.springframework.transaction.jta包中,Spring提供的对OC4J10.1.3+应用服务器事务管理器的适配器,此适配器用于对应用服务器提供的高级事务的支持;
WebSphereUowTransactionManager:位于org.springframework.transaction.jta包中,Spring提供的对WebSphere 6.0+应用服务器事务管理器的适配器,此适配器用于对应用服务器提供的高级事务的支持;
WebLogicJtaTransactionManager:位于org.springframework.transaction.jta包中,Spring提供的对WebLogic 8.1+应用服务器事务管理器的适配器,此适配器用于对应用服务器提供的高级事务的支持。
Spring不仅提供这些事务管理器,还提供对如JMS事务管理的管理器等,Spring提供一致的事务抽象如图所示

spring与hibernate

说明:

spring在调用具体的事务管理器之前做了一些准备工作,提前设置事务的读写策略,而这些事务策略是公共的东西,是写在spring的配置文件中的,这些内容的处理需要放在抽象类中去做

二、spring与hibernate整合中的事务处理

1.2 以xml形式
引入properties配置文件

 <property name="locations">
   <value>classpath:jdbc.properties</value>
 </property> 

配置dbcp数据源

<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
 </bean> 

引入sessionfactory,使用hibernate外部配置文件

<bean id="sessionFactory2" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="configLocation">
      <value>classpath:hibernate.cfg.xml</value>
    </property>
</bean> 

注入dao和service层

  <bean id="personDao" class="cn.qjc.hibernate.dao.impl.PersonDaoImpl">
    <property name="sessionFactory">
      <ref bean="sessionFactory2"/>
    </property>
  </bean> 

  <bean id="personService" class="cn.qjc.hibernate.service.impl.PersonServiceImpl">
    <property name="personDao">
      <ref bean="personDao"/>
    </property>
  </bean>

配置hibernate事务管理器

  <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory">
      <ref bean="sessionFactory2"/>
    </property>
   </bean>

配置声明式事务

作用:

  1、告诉spring容器事务管理器

  2、告诉spring容器什么样的方法使用什么样的事务

  <tx:advice transaction-manager="transactionManager" id="tx">
    <tx:attributes>
      <!--
        name 目标方法的范围
        islation 隔离级别
        propagation 传播属性
        read-only
          true 只读事务
          false 读写事务
       -->
      <tx:method name="save*" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/>
    </tx:attributes>
   </tx:advice>

配置切入点

  <aop:config>
    <aop:pointcut expression="execution(* cn.qjc.hibernate.service.impl.*.*(..))" id="perform"/>
      <span style="white-space:pre"> </span><!-- 将切入点应用到增强方法 -->
    <aop:advisor advice-ref="tx" pointcut-ref="perform"/>
   </aop:config>

dao实现类

 * 实现方法一:继承HibernateDaoSupport
 * @author qjc
 */
public class PersonDaoImpl extends HibernateDaoSupport implements PersonDao{ 

  @Override
  public void savePerson(Person person) {
    this.getHibernateTemplate().save(person);
  }
}

测试

...

注意:

1、如果一个DAO类继承了HibernateDaoSupport,只需要在spring配置文件中注入SessionFactory就可以了。

2、如果一个DAO类没有继承HibernateDaoSupport,需要有一个SessionFactory的属性,并且在配置文件中进行注入。

  <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
    <property name="sessionFactory" ref="sessionFactory2"></property>
  </bean>

1.2 以注解形式

1、在配置文件中应用spring的自动扫描机制

<context:component-scan base-package="cn.qjc"/>

2、在配置文件中引入注解解析器

<tx:annotation-driven transaction-manager="transactionManager"/>

3、在service层通过@Transaction进行注解

注意:如果在类级别上被注解为只读事务,但是这个类中的方法中@Transaction注解的事务设置将优先于类级别注解的事务设置。

1.3 spring事务的传播属性

  required: 业务方法需要在一个事务中运行。如果方法运行时,已经处在一个事务中,那么加入到该事务,否则为自己创建一个新事务(默认)

  not-supported:spring容器不开启事务,如果方法在一个事务中被调用,该事务会被挂起,该方法结束后,事务恢复

  requiresnew:不管是否存在事务,业务方法总会创建一个新事务。

  mandatorky: 业务方法只能在一个已经存在的事务中执行,如果业务方法在没有事务下调用,容器抛出例外。

此外还有supports、never、nested等属性,但是通常使用默认

propagation="required" 此配置可以解决事务嵌套问题,何为事务嵌套?

比如:

在工作流框架和操作service层的某个方法中都存在事务,service层也有自己的事务,当service执行的时候,就会出现事务嵌套,即方法本身有事务,方法中的方法还有事务,这就是事务嵌套。而spring通过事务传播属性propagation="required"解决了这一问题。

1.4 OpenInSessionView

在s2sh整合以后,spring管理事务,由于使用的是spring的声明式事务处理方式,所以在调用this.getHibernateTemplate()这个方法执行完之后,session立即关闭,如果当前执行的方法有事务,当事务环境的方法被调用完毕后session关闭。所以当值在页面输出时会产生异常。

处理方式为:OpenSessionInview模式(web.xml中配置)

<filter>
  <filter-name>hibernateFilter</filter-name>
  <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class> 

  <!-- singleSession默认为true,若设置为false则等于没有OpenSessionInView -->
  <init-param>
    <param-name>singleSession</param-name>
    <param-value>true</param-value>
  </init-param>
 </filter> 

 <filter-mapping>
  <filter-name>hibernateFilter</filter-name>
  <url-pattern>/PersonService</url-pattern>
 </filter-mapping>

从上面代码可以看出,当提交一个请求时,OpenSessionInView中已经把session开启了,在response以后才要关闭session,也就意味着有了openSessionInView必须在struts2的过滤器之前。(放struts2过滤器位置上面)

但是开启OpenSessionInView也有缺点:因为session关闭被延后了,而hibernate的一级缓存在session中,所以会导致大量的缓存中的数据被长时间停留在内存中。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • spring声明式事务管理解析

    前沿:通过对spring事务管理有了比较深入学习,本文将不做实例,而是指定具体的类和配置文件进行讲解. 本文内容: 1.了解什么是声明式事务? 2.声明式事务管理分别有哪几种? 3.这几种事务管理之间的区别是什么? 一.什么是声明式事务? 声明式事务(declarative transaction management)是spring提供的对程序事务管理的方式之一.Spring的声明式事务就是采用声明的方式来处理事务,用在Spring配置文件中声明式的处理事务来代替代码式的处理事务.这样的好处是

  • Spring的编程式事务和声明式事务详解

    入口(了解一些基本概念) Spring事务属性(事务的属性有哪些?) 我们都知道事务有开始,保存点,提交,回滚,隔离级别等属性.那么Spring对于事务属性定义有哪些呢?通过TransactionDefinition接口我们可以了解到: public interface TransactionDefinition{ int getIsolationLevel(); int getPropagationBehavior(); int getTimeout(); boolean isReadOnly

  • 完美解决Spring声明式事务不回滚的问题

    疑问,确实像往常一样在service上添加了注解 @Transactional,为什么查询数据库时还是发现有数据不一致的情况,想想肯定是事务没起作用,出现异常的时候数据没有回滚.于是就对相关代码进行了一番测试,结果发现一下踩进了两个坑,确实是事务未回滚导致的数据不一致. 下面总结一下经验教训: Spring事务的管理操作方法 编程式的事务管理 实际应用中很少使用 通过使用TransactionTemplate 手动管理事务 声明式的事务管理 开发中推荐使用(代码侵入最少) Spring的声明式事

  • springboot开启声明式事务的方法

    springboot开启事务很简单,只需要一个注解@Transactional 就可以了.因为在springboot中已经默认对jpa.jdbc.mybatis开启了事事务,引入它们依赖的时候,事物就默认开启.当然,如果你需要用其他的orm,比如beatlsql,就需要自己配置相关的事物管理器. 准备阶段 以上一篇文章的代码为例子,即springboot整合mybatis,上一篇文章是基于注解来实现mybatis的数据访问层,这篇文章基于xml的来实现,并开启声明式事务. 环境依赖 在pom文件

  • spring声明式事务解析

    一.spring声明式事务 1.1 spring的事务管理器 spring没有直接管理事务,而是将管理事务的责任委托给JTA或相应的持久性机制所提供的某个特定平台的事务实现.spring容器负责事物的操作,spring容器充当切面,事务的方法称为增强处理,生成的代理对象的方法就是目标方法+增强也就是crud+事务程序员只用做crud的操作,也就是目标方法和声明哪些方法应该在事务中运行. Spring提供了许多内置事务管理器实现: DataSourceTransactionManager:位于or

  • spring 声明式事务实现过程解析

    这篇文章主要介绍了spring 声明式事务实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 /** * 声明式事务: * * 环境搭建: * 1.导入相关依赖 * 数数据 * 3.给方法上标注 @Transactional 表示当前方法是一个事务方法: * 4. @EnableTransactionManagement 开启基于注解的事务管理功能:据源.数据库驱动.Spring-jdbc模块 * * 2.配置数据源.JdbcTempl

  • Spring声明式事务注解之@EnableTransactionManagement解析

    Spring声明式事务注解之@EnableTransactionManagement 1. 说明 @EnableTransactionManagement声明在主配置类上,表示开启声明式事务,其原理是通过@Import导入TransactionManagementConfigurationSelector组件,然后又通过TransactionManagementConfigurationSelector导入组件AutoProxyRegistrar和ProxyTransactionManageme

  • spring声明式事务@Transactional底层工作原理

    目录 引言 工作机制简述 事务AOP核心类释义 @Transactional TransactionAttribute SpringTransactionAnnotationParser AnnotationTransactionAttributeSource TransactionAttributeSourcePointcut TransactionInterceptor BeanFactoryTransactionAttributeSourceAdvisor ProxyTransaction

  • spring声明式事务 @Transactional 不回滚的多种情况以及解决方案

    目录 一. spring 事务原理 问题一.@Transactional 应该加到什么地方,如果加到Controller会回滚吗? 问题二. @Transactional 注解中用不用加rollbackFor = Exception.class 这个属性值 问题三:事务调用嵌套问题具体结果如下代码: 四.总结 五. 参考链接 本文是基于springboot完成测试测试代码地址如下: https://github.com/Dr-Water/springboot-action/tree/master

  • Spring声明式事务配置使用详解

    目录 序章 准备工作 创建jdbc.properties 配置Spring的配置文件 声明式事务概念 代码讲解 配置 Spring 的配置文件 创建表 创建组件 测试无事务情况 加入事务 序章 Spring 框架对 JDBC 进行封装,使用 JdbcTemplate 方便实现对数据库操作 准备工作 <dependencies> <!-- 基于Maven依赖传递性,导入spring-context依赖即可导入当前所需所有jar包 --> <dependency> <

  • Spring声明式事务和@Aspect的拦截顺序问题的解决

    在使用AbstractRoutingDataSource配置多数据源时,发现使用@aspect配置的DataSourceSwitchAspect总是在声明式事务之后执行,配置了Order依然不行,经过调研发现是由于两者的aop代理方式不一致导致. 在spring内部,是通过BeanPostProcessor(<spring 攻略>一书中翻译为,后处理器)来完成自动创建代理工作的.根据匹配规则的不同大致分为三种类别: 1.匹配Bean的名称自动创建匹配到的Bean的代理,实现类BeanNameA

  • Java Spring 声明式事务详解

    目录 项目结构: 表结构: 基于xml的声明式事务配置 完全注解(零xml)方式配置 事务参数 no-rollback-for rollback-for read-only timeout isolation propagation 总结 项目结构: 表结构: 基于xml的声明式事务配置 IAccountDao.java: package tx.dao; import java.math.BigDecimal; public interface IAccountDao { void add(St

随机推荐