Spring事务之事务控制方式

一、编程式事务控制

JDBC的事务管理在Spring2.0下有两种编程式的实现

  • PlatformTransactionManager
  • TransactionTemplate

1、PlatformTransactionManager 事务管理器

package org.springframework.transaction;
public abstract interface PlatformTransactionManager
{
  //根据事务定义TransactionDefinition,获取事务
  public abstract TransactionStatus getTransaction(TransactionDefinition paramTransactionDefinition)
    throws TransactionException;
  //提交事务
  public abstract void commit(TransactionStatus paramTransactionStatus)
    throws TransactionException;
  //回滚事务
  public abstract void rollback(TransactionStatus paramTransactionStatus)
    throws TransactionException;
}

(1)TransactionDefinition : 事务的一些基础信息,如超时时间、隔离级别、传播属性等
(2)TransactionStatus : 事务的一些状态信息,如是否是一个新的事务、是否已被标记为回滚
在使用的过程中常常使用它的最终实现类DataSourceTransactionManager。

public abstract class AbstractPlatformTransactionManager
  implements PlatformTransactionManager, Serializable{
}
public class DataSourceTransactionManager extends AbstractPlatformTransactionManager
  implements ResourceTransactionManager, InitializingBean{
}

具体实现步骤:
1. 实例化的时候,需要用个数据源作参数
2. 建立事务的定义,使用DefaultTransactionDefinition类,直接new个新的就可以了
3. 调用DefaultTransactionDefinition类的setPropagationBehavior方法,参数是TransactionDefinition的常量,例如PROPAGATION_REQUIRED等。
4. 在使用到具体的SQL操作之前,创建一个TransactionStatus类的实例: TransactionStatus status = transactionManager.getTransaction(def)。
其中,transactionManager是DataSourceTransactionManager类的实例,def是DefaultTransactionDefinition的实例
5. 之后使用具体的SQL操作,发生异常了,就使用transactionManager.rollback(status)
6. 正常操作的话,就使用transactionManager.commit(status)
举例:

public void insert(){
    PlatformTransactionManager tran = new DataSourceTransactionManager(dataSource);
    DefaultTransactionDefinition def = new DefaultTransactionDefinition();//事务定义类
    def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
    TransactionStatus status = tran.getTransaction(def);//返回事务
    try {
      JdbcTemplate template = new JdbcTemplate(dataSource);
      template.update("Insert into userinfo(username,password) values('aaaaa','bbbbb')");
      template.update("Insert into userinfo(username,password) values('ccccc','ddddd')");
      tran.rollback(status);      
    } catch (Exception e) {
      tran.rollback(status);
      e.printStackTrace();
    }
  }

  由于Spring容器底层采用ThreadLocal存储事务当前线程的Connection,所以DataSourceTransactionManager中操作Connection对象和JdbcTemplate中操作的Connection是同一个对象(详情见另一博文:《Spring中事务之如何保证同一个Connection对象》),因此能够DataSourceTransactionManager能够代理管理JdbcTemplate的事务。

PlatformTransactionManager源码详细分析见:
http://www.07net01.com/2015/05/842465.html

2、TransactionTemplate 事务模板
  TransactionTemplate模板类用于简化事务管理,事务管理由模板类定义,而具体操作需要通过TransactionCallback回调接口或TransactionCallbackWithoutResult回调接口指定,通过调用模板类的参数类型为TransactionCallback或TransactionCallbackWithoutResult的execute方法来自动享受事务管理。
  TransactionTemplate模板类使用的回调接口:

  • TransactionCallback:通过实现该接口的“T doInTransaction(TransactionStatus status) ”方法来定义需要事务管理的操作代码;
  • TransactionCallbackWithoutResult:继承TransactionCallback接口,提供“void doInTransactionWithoutResult(TransactionStatus status)”便利接口用于方便那些不需要返回值的事务操作代码。

具体步骤:
1. 在具体的SQL语句操作签,实例化它:

TransactioinTemplate transactionTemplate = new TransactionTemplate(trasactionManager);

2. 然后就是具体的SQL操作,不过写起来有点复杂:

transactionTemplate.execute(
   new TransactionCallback() {
      public Object doInTransaction(TransactionStatus status) {
      // 这里执行SQL的操作
      // 发生异常的时候status.setRollbackOnly(),正常的时候直接返回结果
      }
   }
);

3.如果没有返回值,可以使用TransactionCallbackWithoutResult类。里面的方法调用一样,只不过用了TransactionCallbackWithoutResult的匿名继承。

举例:

public void update(){
    DataSourceTransactionManager tran = new DataSourceTransactionManager(dataSource);
    TransactionTemplate tranTemplate = new TransactionTemplate(tran);
    tranTemplate.execute(new TransactionCallback() {

      @Override
      public Object doInTransaction(TransactionStatus status) {
        int retInt = 0;
        try {
          JdbcTemplate template = new JdbcTemplate(dataSource);
          template.update("udpate userinfo set password = 'mbbbb' where username = 'aaaaa' ");
          template.update("udpate userinfo set password = 'mdddd' where username = 'ccccc' ");
          retInt = 1;
        } catch (Exception e) {
          status.setRollbackOnly();//通知回滚
          e.printStackTrace();
        }
        return new Integer(retInt);
      }
    });
  }

二、XML配置(AOP)事务控制

在Spring配置文件中配置如下


<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="org.gjt.mm.mysql.Driver" />
        <property name="url"
            value="jdbc:mysql://localhost:3306/test?userUnicode=true&characterEncoding=UTF-8" />
        <property name="username" value="root" />
        <property name="password" value="5" />
        
        <property name="initialSize" value="1" />
        
        <property name="maxActive" value="500" />
        
        <property name="maxIdle" value="2" />
        
        <property name="minIdle" value="1" />
    bean>
    
    <bean id="txManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    bean>
    
    <tx:advice id="txAdvice" transaction-manager="txManager">
        <tx:attributes>
            <tx:method name="save*" propagation="REQUIRED" />
            <tx:method name="insert*" propagation="REQUIRED" />
            <tx:method name="delete*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="*" read-only="true" propagation="NOT_SUPPORTED" />
        tx:attributes>
    tx:advice>
    
    <aop:config>
        <aop:pointcut id="transactionPointcut"
            expression="execution(* com.haiwi.service.impl.*.*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="transactionPointcut" />
    aop:config>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource" />
    bean>

    <bean id="bookService" class="com.ufgov.fm.server.serviceimpl.BookServiceImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate" />
    bean>
beans>

下面是Spring中Propagation类的事务属性详解:

  • REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
  • SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
  • MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。
  • REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
  • NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
  • NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
  • NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。

service代码如下

package com.haiwi.service;
public interface BookService {
  public void insertBook();

}
package com.haiwi.service.impl;
import org.springframework.jdbc.core.JdbcTemplate;
import com.haiwi.service.BookService;
public class BookServiceImpl implements BookService {
  JdbcTemplate jdbcTemplate ;
  public JdbcTemplate getJdbcTemplate() {
    return jdbcTemplate;
  }
  public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
    this.jdbcTemplate = jdbcTemplate;
  }
  public void insertBook() {
    jdbcTemplate.update("update book set book_type='编程语言' where cate = '001'");
    jdbcTemplate.update("update book set book_type='数据库' where cate = '002'");
    jdbcTemplate.update("update book set book_type='操作系统' where cate = '003'");
  }
}

你可能感兴趣的:(Java,Java:Spring)