spring框架中的事务管理

来源:互联网 发布:金日十数据 编辑:程序博客网 时间:2024/04/30 10:31

一、概述

(一)基本概念

1 、什么是Spring事务处理?

什么是事务处理我就不想回答了。 Spring 的事务处理,可以说是 Spring AOP 的一种实现。因为事务处理是所谓方面( Aspect )的一个子集。因此默认情况下,事务处理是利用 Java 动态代理机制实现的,这样就必须先定义一个接口,然后再编写实现;而对于没有接口的 Javabean ,则通过 CGLIB 实现。这部分是 Spring AOP 部分的内容。

2 、两种事务处理方式

和 EJB 一样, Spring 也提供两种事务处理方式,一种是编程式事务处理;一种是声明式事务处理。

(二)框架图

实现事务处理的两种方式

Java 动态代理

CGLIB

 

两种事务处理方式

编程式事务处理

声明式事务处理

 

(三)何时使用什么

          如果需要大量的事务处理,就用声明式事务处理,如果很少的事务处理,就用编程式

二、详细

              编程式事务处理与声明式事务处理

(一)编程式事务处理

1 、使用TransactionTemplate进行事务处理(Spring进行commit和rollback)

          ( 1 )使用事务处理的类

 

import javax.sql.DataSource;

import org.springframework.jdbc.core.*;

import org.springframework.transaction.*;

import org.springframework.dao.*;

 

public class bookDAO{

private DataSource dataSource;// 依赖注入 dataSource ,管理数据库

private PlatformTransationManager transactionManager;// 依赖注入管理事务

 

public void setDataSource(DataSource dataSource){

    this.dataSource=dataSource;

}

 

     public void setTransactionManager(PlatformTransationManager transactionManager){

         this. transactionManager= transactionManager;

}

 

public int create(String msg){

    TransactionTemplate transactionTemplate=new TransactionTemplate(transactionManager);

    // 调用 transactionTemplate  execute 方法进行事务管理

    Object result= transactionTemplate.execute (

     // 这是一个回调函数,实现了 TransactionCallback 接口的 doInTransaction 方法,就是在这个方法里写数据库新增数据的操作

          new TransactionCallback()

{

          public Object doInTransaction(TransactionStatus status)

{

              // 数据库操作代码

              return resultObject;

           }

       }

[U1]       )

}

}

如果不想返回结果( resultObject ),则可以用 TransactionCallbackWithoutResult 来实现 TransactionCallback 接口,代码如下:

        new TransactionCallback WithoutResult ()

{

          public Object doInTransaction WithoutResult (TransactionStatus status)

{

              // 数据库操作代码

            

           }

       }

 

( 2 )配置文件

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

 "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

   <!—  定dataSource à

   <bean id=”dataSource” class=”org.springframework.jdbc.datasource.DriverManagerDataSource”>

      <!— 使用SQL Server    à

       <property name=”driverClassName”>

          <value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value>

       </property>

        <property name=”url”>

          <value>jdbc:Microsoft:sqlserver://localhost:1433/stdb</value>

       </property>

<property name=”name”>

          <value>admin</value>

       </property>

<property name=”msg”>

          <value>admin</value>

       </property>

    </bean>

 

    <!— 设定 transactionManager à

    <bean id=”transactionManager”

class=”org.springframework.jdbc.datasource.DataSourceTransactionManager”>

        <property name=”dataSource”>

            <ref bean=”dataSource”/>

        </property>

    </bean>

 

   <!— 示例中 DAO-->

    <bean id=”bookDAO” class=”com.bookDAO”>

        <property name=”dataSource”>

            <ref bean=”dataSource”/>

        </property>

        <property name=”transactionManager”>

            <ref bean=”transactionManager”>

        </property>

   </bean>

</beans>

   这样 Spring 就可以自动进行 commit 和 rollback 这两个操作了。粉色部分是为了和 bookDAO 中的粉色部分相匹配。

2 、使用JdbcTemplate进行事务处理(硬编码进行commit和rollback)

( 1 )使用事务处理的类

 

import javax.sql.DataSource;

import org.springframework.jdbc.core.*;

import org.springframework.transaction.*;

import org.springframework.dao.*;

 

public class bookDAO{

private DataSource dataSource;// 依赖注入 dataSource ,管理数据库

private PlatformTransationManager transactionManager;// 依赖注入管理事务

 

public void setDataSource(DataSource dataSource){

    this.dataSource=dataSource;

}

 

     public void setTransactionManager(PlatformTransationManager transactionManager){

         this. transactionManager= transactionManager;

}

 

public int create(String msg){

  /*  TransactionTemplate transactionTemplate=new TransactionTemplate(transactionManager);

      Object result= transactionTemplate.execute (

       new TransactionCallback()

{

          public Object doInTransaction(TransactionStatus status)

{

 

              return resultObject;

           }

       }

    )*/

  // 使用下面的代码替换上面注释掉的部分

    DefaultTransactionDefinition def =new DefaultTransactionDefinition();

   TransactionStatus status=transactionManager.getTransaction(def);

   try

{

        JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);

        jdbcTemplate.update(“INSERT INTO book VALUES(1,’gf’,’Mastering Spring’)”);

   }

   catch(DataAccessException ex)

{

       transactionzManager.rollback(status);

       throw ex;

   }

   finally

   {

        transactionManager.commit(status);

   }

}

}

( 2 )配置文件

同上

 

( 二)声明式事务处理

( 1 )使用事务处理的类

 

import javax.sql.DataSource;

import org.springframework.jdbc.core.*;

import org.springframework.transaction.*;

import org.springframework.dao.*;

 

public class bookDAO{

private DataSource dataSource;// 依赖注入 dataSource ,管理数据库

private PlatformTransationManager transactionManager;// 依赖注入管理事务

 

public void setDataSource(DataSource dataSource){

    this.dataSource=dataSource;

}

 

     public void setTransactionManager(PlatformTransationManager transactionManager){

         this. transactionManager= transactionManager;

}

 

public int create(String msg){

   /*  TransactionTemplate transactionTemplate=new TransactionTemplate(transactionManager);

      Object result= transactionTemplate.execute (

       new TransactionCallback()

{

          public Object doInTransaction(TransactionStatus status)

{

 

              return resultObject;

           }

       }

    )*/

 

 /*  DefaultTransactionDefinition def=new DefaultTransactionDefinition();

   TransactionStatus status=transactionManager.getTransaction(def);

   try

{

        JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);

        jdbcTemplate.update(“INSERT INTO book VALUES(1,’gf’,’Mastering Spring’)”);

   }

   catch(DataAccessException ex)

{

       transactionzManager.rollback(status);

       throw ex;

   }

    finally

   {

       transactionManager.commit(status);

   } */

// 使用下面的代码替换上面注释掉的部分

     JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);

    jdbcTemplate.update(“INSERT INFO book VALUES(1,’gf’,’Mastering Spring’)”);

/ /   相比,此段代码省去了 commit  rollback 事务处理语句;与  相比,不必实现 TransactionCallback 接口

}

}

( 2 )配置文件

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

 "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

   <!—  定dataSource à

   <bean id=”dataSource” class=”org.springframework.jdbc.datasource.DriverManagerDataSource”>

      <!— 使用SQL Server    à

       <property name=”driverClassName”>

          <value>com.microsoft.jdbc.sqlserver.SQLServerDriver</value>

       </property>

        <property name=”url”>

          <value>jdbc:Microsoft:sqlserver://localhost:1433/stdb</value>

       </property>

<property name=”name”>

          <value>admin</value>

       </property>

<property name=”msg”>

          <value>admin</value>

       </property>

    </bean>

 

    <!— 设定 transactionManager à

    <bean id=”transactionManager”

class=”org.springframework.jdbc.datasource.DataSourceTransactionManager”>

        <property name=”dataSource”>

            <ref bean=”dataSource”/>

        </property>

    </bean>

 

   <!— 示例中 DAO-->

    <bean id=”bookDAO” class=”com.bookDAO”>

        <property name=”dataSource”>

            <ref bean=”dataSource”/>

        </property>

    <!— 与编程式事务处理相比,在 DAO 设置中去掉了这个属性,把它放到了代理类中。 - à

 

    <!—    <property name=”transactionManager”>

            <ref bean=”transactionManager”>

        </property> - à

 

   </bean>

   <!— 声明式事务处理 - à

   <bean id=”bookDAOProxy” class=”org.springframework.transaction.interceptor.Transation.ProxyFactoryBean”>

        <property name=”transacionManager”>

            <ref bean=”transacionMaganer”/>

        </property>

<property name=”target”>

            <ref bean=”bookDAO”/>

        </property>

<property name=”transactionAttributes”>

            <props>

               <!-- 表示对 bookDAO 中的 create 方法进行事务处理,并指明当前没有事务就新建一个(用 PROPAGATION_REQUIRED 常量来表示的) à

                <prop key=”create * ”>PROPAGATION_REQUIRED</prop>

            </props>

        </property>  

   </bean>

</beans>

  续:

事务管理是企业级应用程序中必不可少的一项技术,用于确保数据的完整性和一致性。

作为企业级应用程序框架,Spring在不同的事务管理API上定义了一个抽象层。

程序员不必太了解底层的事务管理API,就能使用Spring事务管理机制。

 

如同EJB中的BMT(Bean-managed transaction,Bean管理事务)和CMT(Container-managed transaction,容器管理事务)方法一样,Spring即支持编程式的事务管理也支持声明式的事务管理。Spring事务支持的目标是给POJO添加事务功能,提供一种EJB事务的可选方法。

 

编程式事务管理:是将事务管理代码嵌入到业务方法中来控制事务的提交和回滚。如果方法正常完成,通常会提交事务;如果方法抛出某种类型的异常,则回滚事务。

然而在使用编程式事务管理时,必须在每个事务操作中包含另外的事务管理代码。因此要在每个操作中重复样板事务代码。此外还很难对不同的应用程序启用和禁用事务管理。事务管理是横切关注点。

 

声明式事务管理:在大多数情况下要比编程式事务管理更好用。它将事务管理代码从业务中分离出来,以声明的方式来实现事务管理。事务管理作为一种横切关注点,可以通过AOP方法模块化。Spring同Spring AOP框架支持声明式事务管理。这样可以帮助你更加轻松的为应用程序启用事务,并定义一致的事务策略。然而,声明式事务管理不太灵活,因为无法通过代码精确的控制事务。

 

事务属性:

原子性

一致性

隔离性

持久性

 

1.选择事务管理器实现

问题:一般情况下,如果应用程序只涉及单个数据源,可以只在数据库连接上调用commit()和rollback()方法来管理事务。

然而,如果事务扩展到多个数据源,或者你更喜欢使用JavaEE应用服务器提供的事务管理功能,就可以选择JTA(Java Transaction API,Java事务API)。此外,你可能还需要为不同的对象/关系映射框架(如:Hibernate或JPA)调用不同专用事务API。

因此,必须为不同的技术处理不同的事务API。很难从一组API切换到另一组API。

 

实现方案:PlateformTransactionManager是所有Spring事务管理器的通用接口。Spring内置了几个实现,用于不同事物管理API。

Spring中的事务管理 - lrf8933 - 罗若峰

 如果在应用程序中只需要处理一个数据源,并且通过JDBC进行存取,DataSourceTransactionManager应该满足需求。

如果在JavaEE应用服务器上涌JTA进行事务管理,就应该使用JtaTransactionManager从应该服务器查找事务。

如果使用ORM存取数据库,并且通过JDBC进行存取,就应该选取相应的事务管理器。

 

事务管理器以普通Bean的形式声明在SpringIoC容器里。例如,下面的Bean配置声明了一个DataSourceTransactionManager实例。

它需要设置dataSource属性,以便可以对这个数据源上的连接进行事务管理。

Spring中的事务管理 - lrf8933 - 罗若峰

 

2.用事务管理器API编程式地管理事务

Spring中的事务管理 - lrf8933 - 罗若峰
Spring中的事务管理 - lrf8933 - 罗若峰
 
 
Spring中的事务管理 - lrf8933 - 罗若峰
 
Spring IoC容器:
Spring中的事务管理 - lrf8933 - 罗若峰
  

3.用事务模板编程式地管理事务

Spring中的事务管理 - lrf8933 - 罗若峰

 Spring中的事务管理 - lrf8933 - 罗若峰

Spring中的事务管理 - lrf8933 - 罗若峰
Spring中的事务管理 - lrf8933 - 罗若峰

 

Spring中的事务管理 - lrf8933 - 罗若峰
Spring中的事务管理 - lrf8933 - 罗若峰

 

Spring中的事务管理 - lrf8933 - 罗若峰
Spring中的事务管理 - lrf8933 - 罗若峰
Spring中的事务管理 - lrf8933 - 罗若峰

 

4.用经典的Spring AOP声明式地管理事务

 问题:事务管理是一种横切关注点,AOP是实现它的理想方法。然而,如果要在Spring1.x中声明式地管理事务,就必须使用经典Spring AOP方法。

 

解决方案:Spring为事务管理提供了一个环绕通知,称作TransactionInterceptor。这个通知像事务模板一样控制这事务管理流程,但它使用于整个方法体,而不是任意的代码块。默认情况下,在方法开始之前,这个通知就启动了一个新的事务。如果方法抛出未受检的异常,上午就被回滚。否则完成方法之后就提交事务。

在经典Spring AOP中,必须利用ProxyFactoryBean为Bean创建一个代理来应用TransactionInterceptor通知。由于事务管理在企业应用中非常普遍,因此Spring提供了一个TransactionProxyFactoryBean类,它专用于创建事务代理。

 Dao类:

Spring中的事务管理 - lrf8933 - 罗若峰

 Spring IoC容器:

Spring中的事务管理 - lrf8933 - 罗若峰
Spring中的事务管理 - lrf8933 - 罗若峰

 Main类:

Spring中的事务管理 - lrf8933 - 罗若峰

 

Spring中的事务管理 - lrf8933 - 罗若峰

 

 

5.用事务通知声明式的管理事务

Spring中的事务管理 - lrf8933 - 罗若峰
Spring中的事务管理 - lrf8933 - 罗若峰
Spring中的事务管理 - lrf8933 - 罗若峰
Spring中的事务管理 - lrf8933 - 罗若峰
Spring中的事务管理 - lrf8933 - 罗若峰

 Main类:

Spring中的事务管理 - lrf8933 - 罗若峰

 

6.用@Transactional注解声明式地管理事务

Spring中的事务管理 - lrf8933 - 罗若峰
Spring中的事务管理 - lrf8933 - 罗若峰

 Spring IoC容器:

Spring中的事务管理 - lrf8933 - 罗若峰

 

Spring中的事务管理 - lrf8933 - 罗若峰

 

7.设置传播事务属性

问题描述:当事务方法别另一个方法调用时,必须制定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能启动一个新事务,并在它自己的事务中运行。

 

解决方法:事务的传播行为可以由传播事务属性制定。Spring定义了7种传播行为,这些行为时在org.springframework.transaction.TransactionDefinition中定义的。并非所有事务管理器类型都支持这些传播行为。

Spring中的事务管理 - lrf8933 - 罗若峰

0 0