jacksun1978

导航

 

事务之间可能存在的三个问题:脏读取,不可重复读取和幻影行

PlatformTransactionManager接口:

Spring 事务管理的抽象关键在于PlatformTransactionManager接口的实现,通过依赖与PlatformTansactionManager接口和各种技术的实现,Spring提供开发者使用一致的编程模型,即使使用的是不同的事务管理技术。

public interface PlatformTransactionManager{

  TansactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;

  void commit(TransactionStatus status) throws TransactionException;

  void rollback(TransactionStatus status) throws TransactionException;

}

TransactionException 是 Unchecked Exception,Spring不强迫开发者一定要处理,而是可以自行选择是否要捕捉异常。

TransactionDefinition 定义了事务的传播属性,隔离级别,只读和超时等属性。

TransactionStatus代表了一个新的事务或者已经存在的事务,通过它来控制事物的执行的状态。

 

Spring提供了编程式事务控制和声明式事务控制。

编程式事务控制可以清楚的控制事务的边界,也就是自行定义事务开始,撤销和结束等操作的时间,实现细粒度的事务控制。

声明式事务控制

声明式事务控制可以实现非侵入性的程序开发,通过配置文件将对象纳入到事务管理中。

 

Spring提供两种方式实现编程事务管理,一种是通过PlatformTransactionManager的实现,一种是通过org.springframework.transaction.support.TransactionTemplate

 

声明式事务管理:

1、通过纯粹的xml实现事务控制实例:

package com.highsoft.study.service;
public interface FooService {
    public String getFooName();
    public void insertFoo();
} 

   

package com.highsoft.study.service;

import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;;

public class DefaultFooService implements FooService {
    private Log log=LogFactory.getLog(this.getClass());
    private JdbcTemplate jdbcTemplate;
    @Autowired
    public void init(DataSource dataSource){
        jdbcTemplate = new JdbcTemplate(dataSource);
        log.debug("init");
    }
    public String getFooName() {
        return "Foo";
    }


    public void insertFoo() {
        this.jdbcTemplate.update("insert into vets(id,first_name,last_name) values('8','11','22')");
        this.jdbcTemplate.update("inser into vets(id,first_name,last_name) values('9','11','22')");
    }

}

applicationContext.xml:

    <import resource="applicationContext-dataSource.xml"/>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
   
    <context:annotation-config />

   
    <bean id="fooService" class="com.highsoft.study.service.DefaultFooService"></bean>
   
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="get*" read-only="true"/>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    <aop:config>
        <aop:pointcut expression="execution(* com.highsoft.study.service.*.*(..))" id="services"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="services"/>
    </aop:config>


2、@Transactional注解

实例:

@Service
public class DefaultFooService implements FooService {
    private Log log=LogFactory.getLog(this.getClass());
    private JdbcTemplate jdbcTemplate;
    @Autowired
    public void init(DataSource dataSource){
        jdbcTemplate = new JdbcTemplate(dataSource);
        log.debug("init");
    }
    public String getFooName() {
        return "Foo";
    }

   @Transactional(readOnly=false,propagation = Propagation.REQUIRED)
    public void insertFoo() {
        this.jdbcTemplate.update("insert into vets(id,first_name,last_name) values('8','11','22')");
        this.jdbcTemplate.update("inser into vets(id,first_name,last_name) values('9','11','22')");
    }

}

applicationContext.xml:

    <import resource="applicationContext-dataSource.xml"/>
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
   
   <aop:aspectj-autoproxy/>
    <context:annotation-config/>
    <bean id="fooService" class="com.highsoft.study.service.DefaultFooService"></bean>

特别要注意的几个问题,这几个问题可能导致事务控制失败:

  1、事务控制通过AOP来实现。

  2、在applicationContext声明需要进行事务控制的bean,像fooService

  3、事务控制的方法要进行回滚,要抛出异常,不能用try catch来进行处理。。像insertFoo方法

提示:如果用‘transactionManager’来定义PlatformTransactionManager bean的名字,就可以省略<tx:annotation-driven/>标签中的transaction-manager属性。如果用其他的名字,则必须在<tx:annotation-driven/>标签中定义transaction-manager属性。

 

在使用代理的时候,@Transactional注解应该只被应用到public方法中。如果非要注解非public方法的话,参考AspectJ。

@Transactional注解可以被应用在接口定义,接口方法,类定义和类方法上。Spring团队建议只讲@Transactional注解应用在具体的类上,而不应用在接口上。

 

只是应用@Transactional不会启用事务管理,正是<tx:annotation-driven/>标签开启了事务管理。

 

注意:在代理模式下(默认情况),只有从代理传过来的外部调用才会被拦截,“自我调用”是不会触发事务的。要实现“自我调用”也触发事务,使用AspectJ

 

<tx:annotation-driven/>的设置:

transaction-manager:事务管理器的名字,默认值:transactionManager

mode:模式,默认值:proxy

proxy-target-class:基于类代理还是基于接口代理,只对代理模式有效。默认false。。不设或者设为false,表示基于接口代理

order:顺序

 

@Transactional设置:

propagation:事务传播性设置,Propagation枚举类型。Spring支持的事务传播属性包括7种:

    PROPAGATION_MANDATORY:方法必须在事务中执行,否则抛出异常。

    PROPAGATION_NESTED:使方法运行在嵌套事务中,否则和PROPAGATION_REQUIRED一样。

    PROPAGATION_NEVER :当前方法永远不在事务中运行,否则抛出异常。

    PROPAGATION_NOT_SUPPORTED:定义为当前事务不支持的方法,在该方法执行期间正在运行的事务会被暂停

    PROPAGATION_REQUIRED:当前的方法必须运行在事务中,如果没有事务就新建一个事务。新事务和方法一起开始,随着方法返回或者抛出异常时终止。

    PROPAGATION_REQUIRED_NEW :当前方法必须新建一个事务,如果当前的事务正在运行则暂停。

    PROPAGATION_SUPPORTS :规定当前方法支持当前事务,但是如果没有事务在运行就使用非事务方法执行。

isolation:事务隔离性级别设置,Isolation枚举类型

    ISOLATION_DEFAULT :使用数据库默认的隔离级别

    ISOLATION_COMMITTED:允许其他事务已经提交的更新(防止脏读取)

    ISOLATION_READ_UNCOMMITTED:允许读取其他事务未提交的更新,会导致三个缺陷发生。执行速度最快

    ISOLATION_REPEATABLE_READ :除非事务自身更改了数据,否则事务多次读取的数据相同(防止脏数据,多次重复读取)

    ISOLATION_SERIALIZABLE:隔离级别最高,可以防止三个缺陷,但是速度最慢,影响性能。

 

readOnly:读写性事务,只读性事务,布尔型

    对数据库的操作中,查询是使用最频繁的操作,每次执行查询时都要从数据库中重新读取数据,有时多次读取的数据都是相同的,这样的数据操作不仅浪费了系统资源,还影响了系统速度。对访问量大的程序来说,节省这部分资源可以大大提    升系统速度。

   将事务声明为只读的,那么数据库可以根据事务的特性优化事务的读取操作

timeout:超时时间,单位秒

事务可能因为某种原因很长时间没有反应,这期间可能锁定了数据库表,影响性能。设置超时时间,如果超过该时间,事务自动回滚。

rollbackFor:一组异常类的实例,遇到时必须进行回滚

rollbackForClassname:一组异常类的名字,遇到时必须进行回滚

noRollbackFor:一组异常类的实例,遇到时必须不回滚

noRollbackForClassname:一组异常类的名字,遇到时必须不回滚

posted on 2011-10-21 10:34  jacksun1978  阅读(613)  评论(0编辑  收藏  举报