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配置文件中配置如下

<?xml version="1.0" encoding="UTF-8"?>
<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&amp;characterEncoding=UTF-8" />
        <property name="username" value="root" />
        <property name="password" value="5" />
        <!-- 连接池启动时的初始值 -->
        <property name="initialSize" value="1" />
        <!-- 连接池的最大值 -->
        <property name="maxActive" value="500" />
        <!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 -->
        <property name="maxIdle" value="2" />
        <!-- 最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 -->
        <property name="minIdle" value="1" />
    </bean>
    <!-- 配置DataSourceTransactionManager事务 -->
    <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'");
  }
}
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值