`

Spring事务管理及与mybatis3整合的事务管理

阅读更多

数据访问事务处理 in Spring+Mybatis3.0

事务---保证了用户的每一次操作都是可靠的,即使出现了异常的访问,也不至于破坏后台数据的完整性;

Java事务简介

事务必须符合ISO/IEC所定制的ACID原则

1)       A(atomicity):原子性

在事务执行的过程中,任何的失败就将导致事务的任何修改失效,

2)       C(consistency):一致性

事务回滚时,事务所执行的内容必须恢复到初始状态,即事务执行前的状态

3)       I(isolation):隔离性

事务执行过程中对数据的修改,在提交之前的数据对其他事务不可见

4)       D(durability):持久性

已经提交的数据在事务执行失败时,数据的状态都是正确的.

事务分类:

全局事务(分布式事务):

        由应用服务器来管理(JTA),同时可以用于多个事务性的资源;

本地事务

本地事务和资源相关,主要通过JDBC来实现

在实际应用中,存在一种容器管理事务,容器事务主要是由javaEE应用服务器提供,容器事务大多给予JTA完成,事实上这是在容器中覆盖了JDBCJTA事务.

事务特性分析(use spring)

TransactionDefinition 接口来定义事务属性。

Code:

public  interface TransactionDefinition{

int getIsolationLevel();

int getPropagationBehavior();

int getTimeout();

boolean isReadOnly();

}

事务机制

a)      事务隔离级别

隔离级别是指若干个并发的事务之间的隔离程度。TransactionDefinition 接口中定义了五个表示隔离级别的常量:

    TransactionDefinition.ISOLATION_DEFAULT(默认值):表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是TransactionDefinition.ISOLATION_READ_COMMITTED

    TransactionDefinition.ISOLATION_READ_UNCOMMITTED:该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读和不可重复读,因此很少使用该隔离级别。

    TransactionDefinition.ISOLATION_READ_COMMITTED:该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。

    TransactionDefinition.ISOLATION_REPEATABLE_READ:该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。即使在多次查询之间有新增的数据满足该查询,这些新增的记录也会被忽略。该级别可以防止脏读和不可重复读。

TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

隔离级别定义了事务与事务之间的隔离程度。

隔离级别与并发性是互为矛盾的:隔离程度越高,数据库的并发性越差;隔离程度越低,数据库的并发性越好。

    ANSI/ISO SQL92标准定义了一些数据库操作的隔离级别:

        未提交读(read uncommitted)

        提交读(read committed)

        重复读(repeatable read)

        序列化(serializable)

通过一些现象,可以反映出隔离级别的效果。这些现象有:

更新丢失(lost update):当系统允许两个事务同时更新同一数据是,发生更新丢失。

脏读(dirty read):当一个事务读取另一个事务尚未提交的修改时,产生脏读。

非重复读(nonrepeatable read):同一查询在同一事务中多次进行,由于其他提交事务所做的修改或删除,每次返回不同的结果集,此时发生非重复读。(A transaction rereads data it has previously read and finds that another committed transaction has modified or deleted the data.)

幻读(phantom read):同一查询在同一事务中多次进行,由于其他提交事务所做的插入操作,每次返回不同的结果集,此时发生幻像读。(A transaction reexecutes a query returning a set of rows that satisfies a search condition and finds that another committed transaction has inserted additional rows that satisfy the condition.)

隔离级别影响部分:

 

b)       事务传播行为

所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。在TransactionDefinition定义中包括了如下几个表示传播行为的常量:

TransactionDefinition.PROPAGATION_REQUIRED

如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。

TransactionDefinition.PROPAGATION_REQUIRES_NEW

创建一个新的事务,如果当前存在事务,则把当前事务挂起。

TransactionDefinition.PROPAGATION_SUPPORTS

如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。

TransactionDefinition.PROPAGATION_NOT_SUPPORTED

以非事务方式运行,如果当前存在事务,则把当前事务挂起。

TransactionDefinition.PROPAGATION_NEVER

以非事务方式运行,如果当前存在事务,则抛出异常。

TransactionDefinition.PROPAGATION_MANDATORY

如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。

TransactionDefinition.PROPAGATION_NESTED

如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED

                    此处涉及到【嵌套事务】

                      内部事务依赖于外部事务

                              外部事务的提交和回滚直接影响到内部事务(内部事务不是独立的)

c)        事务超时

                    指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务。在 TransactionDefinition 中以 int 的值来表示超时时间,其单位是

d)       事务的只读属性(readOnly

对事务性资源进行只读操作或者是读写操作。所谓事务性资源就是指那些被事务管理的资源,比如数据源、 JMS 资源,以及自定义的事务性资源等等。如果确定只对事务性资源进行只读操作,那么我们可以将事务标志为只读的,以提高事务处理的性能。在 TransactionDefinition 中以 boolean 类型来表示该事务是否只读。

           e)  事务的回滚规则

通常情况下,如果在事务中抛出了未检查异常(继承自 RuntimeException 的异常),则默认将回滚事务。如果没有抛出任何异常,或者抛出了已检查异常,则仍然提交事务。这通常也是大多数开发者希望的处理方式,也是 EJB 中的默认处理方式。但是,我们可以根据需要人为控制事务在抛出某些未检查异常时任然提交事务,或者在抛出某些已检查异常时回滚事务。

TransactionDefinitionPlatformTransactionManagerTransactionStatus

事务管理,其实就是“按照给定的事务规则来执行提交或者回滚操作”。“给定的事务规则”就是用TransactionDefinition 表示的,“按照……来执行提交或者回滚操作”便是用 PlatformTransactionManager 来表示,而 TransactionStatus 用于表示一个运行着的事务的状态。

PlatformTransactionManager 用于执行具体的事务操作。

Public interface PlatformTransactionManager{

  TransactionStatus getTransaction(TransactionDefinition definition)

   throws TransactionException;

   void commit(TransactionStatus status)throws TransactionException;

   void rollback(TransactionStatus status)throws TransactionException;

}

           根据底层所使用的不同的持久化 API 或框架,PlatformTransactionManager 的主要实现类大致如下:

 

    DataSourceTransactionManager:适用于使用JDBCiBatis进行数据持久化操作的情况。

    HibernateTransactionManager:适用于使用Hibernate进行数据持久化操作的情况。

    JpaTransactionManager:适用于使用JPA进行数据持久化操作的情况。

    另外还有JtaTransactionManager JdoTransactionManagerJmsTransactionManager等等。

 

如果我们使用JTA进行事务管理,我们可以通过 JNDI Spring JtaTransactionManager 来获取一个容器管理的 DataSourceJtaTransactionManager 不需要知道 DataSource 和其他特定的资源,因为它将使用容器提供的全局事务管理。而对于其他事务管理器,比如DataSourceTransactionManager,在定义时需要提供底层的数据源作为其属性,也就是 DataSource。与 HibernateTransactionManager 对应的是 SessionFactory,与 JpaTransactionManager 对应的是 EntityManagerFactory 等等。

TransactionStatus

PlatformTransactionManager.getTransaction(…) 方法返回一个 TransactionStatus 对象。返回的TransactionStatus 对象可能代表一个新的或已经存在的事务(如果在当前调用堆栈有一个符合条件的事务)。TransactionStatus 接口提供了一个简单的控制事务执行和查询事务状态的方法。

public  interface TransactionStatus{

   boolean isNewTransaction();

   void setRollbackOnly();

   boolean isRollbackOnly();

}

Spring 的编程式事务管理

Spring 出现以前,编程式事务管理对基于 POJO 的应用来说是唯一选择。用过 Hibernate 的人都知道,需要在代码中显式调用beginTransaction()commit()rollback()等事务管理相关的方法,这就是编程式事务管理。通过 Spring 提供的事务管理 API,我们可以在代码中灵活控制事务的执行。在底层,Spring 仍然将事务操作委托给底层的持久化框架来执行。

声明式事务管理(方便代码维护,无污染,无重复代码,但是粒度控制不够)

Spring 的声明式事务管理在底层是建立在 AOP 的基础之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过等价的基于标注的方式),便可以将事务规则应用到业务逻辑中。因为事务管理本身就是一个典型的横切逻辑,正是 AOP 的用武之地。

通常情况下,笔者强烈建议在开发中使用声明式事务,不仅因为其简单,更主要是因为这样使得纯业务代码不被污染,极大方便后期的代码维护。

基于transactionIntercepter

<beans>

<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">

<property name="transactionManager" ref="transactionManager"/>

<property name="transactionAttributes">

<props>

<prop key="transfer">PROPAGATION_REQUIRED,-XXException,+xxxException</prop>

</props>

</property>

</bean>

<bean id="serviceTarget" class="com.ncs.test.TestService">

<property name="testDao" ref="testDao"/>

</bean>

<bean id="service"  class="org.springframework.aop.framework.ProxyFactoryBean">

<property name="target" ref=" serviceTarget "/>

<property name="interceptorNames">

<list>

<idref bean="transactionInterceptor"/>

</list>

</property>

</bean>

</beans>

我们配置了一个 TransactionInterceptor 来定义相关的事务规则,他有两个主要的属性:一个是 transactionManager,用来指定一个事务管理器,并将具体事务相关的操作委托给它;另一个是 Properties 类型的 transactionAttributes 属性,它主要用来定义事务规则,该属性的每一个键值对中,键指定的是方法名,方法名可以使用通配符,而值就表示相应方法的所应用的事务属性。

 

指定事务属性的取值有较复杂的规则:

格式:

传播行为 [,隔离级别] [,只读属性] [,超时属性] [不影响提交的异常] [,导致回滚的异常]

Ø  传播行为是唯一必须设置的属性,其他都可以忽略,Spring为我们提供了合理的默认值。

Ø  传播行为的取值必须以“PROPAGATION_”开头,具体包括:PROPAGATION_MANDATORYPROPAGATION_NESTEDPROPAGATION_NEVERPROPAGATION_NOT_SUPPORTEDPROPAGATION_REQUIREDPROPAGATION_REQUIRES_NEWPROPAGATION_SUPPORTS,共七种取值。

Ø  隔离级别的取值必须以“ISOLATION_”开头,具体包括:ISOLATION_DEFAULTISOLATION_READ_COMMITTEDISOLATION_READ_UNCOMMITTEDISOLATION_REPEATABLE_READISOLATION_SERIALIZABLE,共五种取值。

Ø  如果事务是只读的,那么我们可以指定只读属性,使用“readOnly”指定。否则我们不需要设置该属性。

Ø  超时属性的取值必须以“TIMEOUT_”开头,后面跟一个int类型的值,表示超时时间,单位

Ø  不影响提交的异常是指,即使事务中抛出了这些类型的异常,事务任然正常提交。必须在每一个异常的名字前面加上“+”。异常的名字可以是类名的一部分。比如“+RuntimeException”、“+tion”等等。

Ø  导致回滚的异常是指,当事务中抛出这些类型的异常时,事务将回滚。必须在每一个异常的名字前面加上“-”。异常的名字可以是类名的全部或者部分,比如“-RuntimeException”、“-tion”等等。

Ø  例子:

<property name="*Service">

PROPAGATION_REQUIREDISOLATION_READ_COMMITTEDTIMEOUT_20+AbcException+DefException-HijException

</property>

 

基于TransactionProxyFactoryBean 的声明式事务管理

前面的声明式事务虽然好,但是配置文件太多。我们必须针对每一个目标对象配置一个ProxyFactoryBean;另外,虽然可以通过父子 Bean 的方式来复用 TransactionInterceptor 的配置,但是实际的复用几率也不高;这样,加上目标对象本身,每一个业务类可能需要对应三个 <bean/> 配置,随着业务类的增多,配置文件将会变得越来越庞大,管理配置文件又成了问题。

为了缓解这个问题,Spring 为我们提供了 TransactionProxyFactoryBean,用于将TransactionInterceptor ProxyFactoryBean 的配置合二为一。

<beans>

<bean id="testServiceTarget"  class="org.test.core.Test">

<property name="testDao" ref="testDao"/>

</bean>

<bean id="testService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

<property name="target" ref=" testServiceTarget "/>

<property name="transactionManager" ref="transactionManager"/>

<property name="transactionAttributes">

<props>

<prop key="transfer">PROPAGATION_REQUIRED</prop>

</props>

</property>

</bean>

</beans>

 

基于 <tx> 命名空间的声明式事务管理

前面两种声明式事务配置方式奠定了 Spring 声明式事务管理的基石。在此基础上,Spring 2.x 引入了 <tx> 命名空间,结合使用 <aop> 命名空间,带给开发人员配置声明式事务的全新体验,配置变得更加简单和灵活。另外,得益于 <aop> 命名空间的切点表达式支持,声明式事务也变得更加强大。

 

XML:

<beans>

<bean id=" testService " class="com.ncs.test testService">

<property name="testDao" ref="testDao"/>

</bean>

<tx:advice id="testAdvice" transaction-manager="transactionManager">

<tx:attributes>

<tx:method name="transfer" propagation="REQUIRED"/>

</tx:attributes>

</tx:advice>

<aop:config>

<aop:pointcut id="testPointcut" expression="execution(* *.transfer(..))"/>

<aop:advisor advice-ref="testAdvice" pointcut-ref="testPointcut"/>

</aop:config>

</beans>

 

简化:

<beans>

<bean id="testService" class=" com.ncs.test testService ">

<property name="testDao" ref="testDao"/>

</bean>

<tx:advice id="testAdvice" transaction-manager="transactionManager">

<aop:config>

<aop:pointcut id="testPointcut" expression="execution(**.transfer(..))"/>

<aop:advisor advice-ref="testAdvice" pointcut-ref="testPointcut"/>

</aop:config>

</beans>

 

基于 @Transactional 的声明式事务管理

事务配置:

         <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

       <property name="dataSource" ref="dataSource" />

</bean>

启用注释:

<tx:annotation-driv

                                           

MyBatis事务管理

MyBatis 中有两种事务管理器类型(也就是 type=[JDBC|MANAGED]”):

  JDBC – 这个配置直接简单使用了JDBC 的提交和回滚设置。它依赖于从数据源得到的连接来管理事务范围。

  MANAGED – 这个配置几乎没做什么。它从来不提交或回滚一个连接。而它会让容器来管理事务的整个生命周期(比如 Spring JEE应用服务器的上下文)。默认情况下它会关闭连接。然而一些容器并不希望这样,因此如果你需要从连接中停止它,将 closeConnection 属性设置为 false。例如:

<transactionManager type="MANAGED">

<property name="closeConnection" value="false"/>

</transactionManager>

这两种事务管理器都不需要任何属性。然而它们都是类型别名,要替换使用它们,你需要放置将你自己的类的完全限定名或类型别名,它们引用了你对 TransacFactory 接口的实现类。

  public interface TransactionFactory {

void setProperties(Properties props);

Transaction newTransaction(Connection conn, boolean autoCommit);

}

  任何在 XML 中配置的属性在实例化之后将会被传递给 setProperties()方法。你的实现类需要创建一个事务接口的实现,这个接口也很简单:

  public interface Transaction {

Connection getConnection();

void commit() throws SQLException;

void rollback() throws SQLException;

void close() throws SQLException;

}

  使用这两个接口,你可以完全自定义 MyBatis 对事务的处理

分享到:
评论

相关推荐

    spring+spring mvc+mybatis框架整合实现超市货物管理系统

    总的来说,"spring+spring mvc+mybatis框架整合实现超市货物管理系统"是一个涵盖后端开发基础技能的项目,涉及了JavaEE的多个层面,从Web层的路由处理,到业务逻辑的实现,再到数据库操作,以及用户认证和分页显示等...

    spring_mybatis 整合jar包

    描述中提到"基本常用jar包的整合",意味着这个压缩包包含了一些基础且常用的库,这些库是进行Spring和MyBatis整合所必需的。例如,Spring的`spring-context`、`spring-beans`、`spring-jdbc`和`spring-tx`,以及...

    Spring3+springmvc+mybatis三大整合

    在"Spring3+SpringMVC+MyBatis"的整合过程中,通常会使用Spring的ApplicationContext来加载配置,管理所有组件。SpringMVC的配置需要定义DispatcherServlet,配置视图解析器如InternalResourceViewResolver,以及...

    spring3.2.6struts2.3.15MyBatis3整合DEMO

    《Spring 3.2.6、Struts 2.3.15与MyBatis 3整合实战详解》 在Java Web开发领域,Spring、Struts和MyBatis是三大主流框架,它们各自承担着不同的职责,共同构建了一个强大的企业级应用开发环境。本DEMO以Spring ...

    mybatis与spring整合的全部jar包

    7. **Spring事务管理**: Spring通过`PlatformTransactionManager`接口提供事务管理服务,它可以控制MyBatis的事务边界,确保数据库操作的一致性。 8. **SpringAOP与MyBatis拦截器**: SpringAOP可以与MyBatis的...

    Spring+SpringMVC+Mybatis框架整合例子(SSM) 下载

    Spring还支持AOP,允许我们编写关注点分离的代码,如日志、事务管理等。 SpringMVC是Spring框架的一部分,专门用于构建Web应用的MVC框架。它负责处理HTTP请求,将请求分发到对应的控制器,控制器处理业务逻辑后,...

    springmvc3+spring+mybatis3整合项目 注解实现

    Spring MVC、Spring 和 MyBatis 是Java开发中常用的三大框架,它们各自负责应用程序的不同层面:Spring MVC 处理Web请求,Spring 提供依赖注入和事务管理,而MyBatis 则是持久层框架,用于数据库操作。这个整合项目...

    mybatis与spring整合全部jar包

    这个“mybatis与spring整合全部jar包”包含了这三个框架整合所需的所有依赖库,使得开发者可以快速搭建SSM项目。 首先,让我们深入了解一下这三个组件: 1. **Spring**:Spring 是一个全面的Java企业级应用开发...

    SpringMybatisSpringMvc整合包

    Spring框架是Java企业级应用的基石,它提供了丰富的功能,包括依赖注入(DI)、面向切面编程(AOP)、事务管理以及容器管理等。在Spring框架中,DI是核心特性,允许开发者将对象的创建和维护交给Spring容器,降低了...

    spring4.3 mybatis3.4 整合

    在IT行业中,Spring框架与MyBatis的整合是常见的企业级应用开发模式,尤其是在Java领域。本项目基于Spring 4.3和MyBatis 3.4进行整合,旨在构建一个SSM(Spring、SpringMVC、MyBatis)集成的多模块Web项目。这个项目...

    spring整合Mybatis

    综上所述,"Spring整合Mybatis"涉及的关键技术点包括:Spring的IoC和事务管理,Mybatis的SQL映射,Mapper接口的使用,以及Mybatis Generator的自动化代码生成。通过合理配置和恰当的代码组织,可以构建出高效稳定的...

    Spring-SpringMVC-Mybatis整合所有jar包

    这个压缩包“Spring-SpringMVC-Mybatis整合所有jar包”包含了这三个框架整合所需的全部依赖,使得开发者能够快速搭建起一个功能完备的后端服务。 1. **Spring框架**:Spring是一个全面的开源应用框架,它提供了对...

    spring+struts2+mybatis整合

    "Spring+Struts2+MyBatis整合"是一个常见的Java Web开发组合,旨在提供强大的控制层、灵活的数据访问以及良好的企业级服务。下面将详细介绍这三个框架以及它们整合的关键点。 **Spring框架**是Java应用开发的核心...

    Spring/SpringMVC/MyBatis整合+事务回滚

    以上就是Spring、SpringMVC和MyBatis整合及事务回滚的基础知识。这个主题涉及到的技能涵盖了Java Web开发的核心部分,对提升开发者解决复杂业务问题的能力大有裨益。在实际开发中,你可能还需要考虑更多细节,如性能...

    spring与Mybatis整合所有jar包

    以上就是Spring与MyBatis整合所需的关键知识点。在实际项目中,还需要根据具体需求进行适当的配置调整和优化,确保框架的高效协同工作。正确配置和理解这些概念对于Java开发者来说至关重要,因为它们构成了许多企业...

    Spring与MyBatis整合源码

    3. **Spring与MyBatis整合**:整合Spring和MyBatis主要涉及以下几个步骤: - **配置数据源**:在Spring的配置文件中,我们需要定义数据源(DataSource),这是连接数据库的关键。 - **配置SqlSessionFactory**:...

    spring与mybatis整合实现事务配置

    **Spring与MyBatis整合的核心步骤:** 1. **引入依赖**:在项目中添加Spring、MyBatis以及数据库驱动的相关jar包,如果使用的是Maven或Gradle,则需在pom.xml或build.gradle中配置相应的依赖。 2. **配置MyBatis**...

    spring4 struts2 mybatis3 maven3 整合

    MyBatis与Spring整合可以实现事务管理,提供动态SQL支持,并且可以方便地通过Spring的数据源配置,实现数据库连接的管理。 **Maven 3** 是一个项目管理和综合工具,通过POM(Project Object Model)文件管理项目的...

    Spring4--Spring4整合mybatis3

    将Spring与Mybatis整合,可以充分利用两者的优点,实现灵活、高效的数据库访问管理。下面我们将深入探讨"Spring4--Spring4整合mybatis3"的相关知识点。 1. **Spring4的IoC(Inversion of Control,控制反转)和AOP...

    Spring SpringMVC Mybatis SSM整合.pdf

    SSM框架整合,即Spring、SpringMVC和Mybatis整合使用,成为了构建企业级Web应用的标准解决方案之一。下面将详细解释Spring、SpringMVC、Mybatis以及SSM整合的相关知识点。 首先,Spring框架是一个开源的Java平台,...

Global site tag (gtag.js) - Google Analytics