spring事务实用开发

来源:互联网 发布:webservice添加数据 编辑:程序博客网 时间:2024/06/05 19:36

一、spring事务简介

spring并不直接管理事务,而是使用事务管理器,本文使用常用的事务管理jdbc.datatsource.DataSourceTransactionManager,

该事务管理器支持JDBC、Mybatis。

二、spring事务配置

1、添加事务管理器org.springframework.jdbc.datasource.DataSourceTransactionManager,即

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">    <property name="dataSource" ref="dataSource" /></bean>
2、添加支持事务的注解配置,即

<aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true" /><tx:annotation-driven transaction-manager="transactionManager" />

3、注解事务使用,在方法上加注解@Transactional,如

@Transactional(propagation = Propagation.REQUIRED,timeout = 3)

三、spring事务的传播行为(Propagation)

spring事务传播行为,缺省的默认值是Propagation.REQUIRED,总的分为七种:

1、Propagation.REQUIRED,即方法必须在事务运行,

如果当前不存在事务,则新启一个事务,

如果当前存在事务,则在当前事务内运行;

该事务传播行为也是缺省的默认值

2、Propagation.MANDATORY,即方法必须是在事务中运行,

如果当前不存在事务,则直接抛出异常;

3、Propagation.NEVER,即方法不能在事务中运行,

如果当存在事务,刚直接抛出异常;

4、Propagation.SUPPORTS,即支持事务,

如果当前存在事务,则在事务中运行,如果不存在,在按无事务运行;

5、Propagation.NOT_SUPPORTED,即不支持事务,

如果当前存在事务,则把当前事务挂起,方法正常运行,方法运行结束后,再挂起的事务接着运行;

6、Propagation.NESTED,即嵌套事务,

如果当前不存在事务,则行为与Propagation.REQUIRED一样;

如果当前存在事务,则在当前事务内新开子事务,同时只有外层事务提交时,子事务才会提交,

同理,外层事务回滚时,子事物也会回滚,但子事务出异常,外层事务是否回滚取决于对子事务异常的处理,

总的说来,它是父事务与子事务的关系,或者说它最终只是一个事务,不存在死锁

7、Propagation.REQUIRES_NEW,即新开事务,

如果当前存在事务,则当前事务挂起,新开一个全新的事务运行,

此时是两个事务(可能出现两个事务相互等待而出现死锁),即挂起的当前事务和新开的事务。

如果当前不存在事务,则新开事务;

四、spring事务超时管理timeout

timeout是spring事务的超时时间值,默认是-1,单位是秒。在事务中,由于各个事务挂起等待,可能出现死锁,所以设置事务的超时时间是有必要的。

五、注意点

1、基于注解的事务,也就是声明式事务,依赖于aop编程,因此如里在当前类中,各事务方法相互间调用,

则aop配置的expose-proxy应设为true,调用时也需做相应处理,详情请查看本博客中的spring中aop开发。

2、使用Propagation.REQUIRES_NEW,则是两个完全独立的事务,

而使用Propagation.NESTED则是父事务与子事务的关系,或者说就只有一个事务。

六、实例

1、添maven依赖

<dependency>    <groupId>org.springframework</groupId>    <artifactId>spring-beans</artifactId>    <version>4.3.4.RELEASE</version></dependency><dependency>    <groupId>org.springframework</groupId>    <artifactId>spring-core</artifactId>    <version>4.3.4.RELEASE</version></dependency><dependency>    <groupId>org.springframework</groupId>    <artifactId>spring-context</artifactId>    <version>4.3.4.RELEASE</version></dependency><dependency>    <groupId>org.mybatis</groupId>    <artifactId>mybatis-spring</artifactId>    <version>1.3.0</version></dependency><dependency>    <groupId>org.springframework</groupId>    <artifactId>spring-jdbc</artifactId>    <version>4.3.4.RELEASE</version></dependency><dependency>    <groupId>org.springframework</groupId>    <artifactId>spring-orm</artifactId>    <version>4.3.4.RELEASE</version></dependency><dependency>    <groupId>org.springframework</groupId>    <artifactId>spring-tx</artifactId>    <version>4.3.4.RELEASE</version></dependency><dependency>    <groupId>org.springframework</groupId>    <artifactId>spring-aop</artifactId>    <version>4.3.4.RELEASE</version></dependency><dependency>    <groupId>org.springframework</groupId>    <artifactId>spring-aspects</artifactId>    <version>4.3.4.RELEASE</version></dependency><dependency>    <groupId>org.springframework</groupId>    <artifactId>spring-asm</artifactId>    <version>3.1.4.RELEASE</version></dependency><dependency>    <groupId>cglib</groupId>    <artifactId>cglib</artifactId>    <version>3.2.4</version></dependency><dependency>    <groupId>org.mybatis</groupId>    <artifactId>mybatis</artifactId>    <version>3.4.4</version></dependency><dependency>    <groupId>mysql</groupId>    <artifactId>mysql-connector-java</artifactId>    <version>5.1.34</version></dependency><dependency>    <groupId>commons-dbcp</groupId>    <artifactId>commons-dbcp</artifactId>    <version>1.4</version></dependency><dependency>    <groupId>commons-pool</groupId>    <artifactId>commons-pool</artifactId>    <version>1.6</version></dependency>
2、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:p="http://www.springframework.org/schema/p"       xmlns:context="http://www.springframework.org/schema/context"       xmlns:tx="http://www.springframework.org/schema/tx"       xmlns:aop="http://www.springframework.org/schema/aop"       xsi:schemaLocation="http://www.springframework.org/schema/beans       http://www.springframework.org/schema/beans/spring-beans.xsd        http://www.springframework.org/schema/context        http://www.springframework.org/schema/context/spring-context.xsd        http://www.springframework.org/schema/tx        http://www.springframework.org/schema/tx/spring-tx.xsd        http://www.springframework.org/schema/aop        http://www.springframework.org/schema/aop/spring-aop.xsd">    <context:component-scan base-package="com.drogon.mybatisStudy" />    <aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true" />        <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">        <property name="locations">            <list>                <value>classpath:properties/env.properties</value>            </list>        </property>    </bean>    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">        <property name="driverClassName" value="${driver}"/>        <property name="url" value="${url}"/>        <property name="username" value="${username}"/>        <property name="password" value="${password}"/>        <property name="maxActive" value="${maxActive}" />        <property name="initialSize" value="${initialSize}" />        <property name="maxWait" value="${maxWait}" />        <property name="maxIdle" value="${minIdle}" />    </bean>    <tx:annotation-driven transaction-manager="transactionManager" />    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">        <property name="dataSource" ref="dataSource" />    </bean>    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">        <!-- mybatis配置文件 -->        <property name="configLocation" value="classpath:mybatis-config.xml"/>        <property name="dataSource" ref="dataSource"/>        <property name="mapperLocations" value="mapper/*.xml"/>        <property name="typeAliasesPackage" value="com.drogon.mybatisStudy.bean"/>        <property name="typeHandlersPackage" value="com.drogon.mybatisStudy.typeHandler"/>    </bean>    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"          p:sqlSessionFactoryBeanName="sqlSessionFactory"          p:basePackage="com.drogon.mybatisStudy.mapper"    /></beans>
3、方法中调用

@Service("stuSerivce")public class StuServiceImpl implements StuSerivce {    @Resource    private StuMapper stuMapper;    @Transactional(propagation = Propagation.REQUIRED,timeout = 3)    @Override    public Stu updateStu(Integer id) {        Stu stu = stuMapper.selectById(id);        stu.setAge(stu.getAge()+1);        stuMapper.upsert(stu);        try{            StuSerivce stuSerivceProxy = (StuSerivce) AopContext.currentProxy();            stuSerivceProxy.updateTution();        }catch (Exception e){            this.updateTution();        }        return stu;    }    @Transactional(propagation = Propagation.REQUIRES_NEW,timeout = 3)    public void updateTution(){        Stu stu = stuMapper.selectById(4);        stu.setTuition(stu.getTuition().add(new BigDecimal(1)));        stuMapper.upsert(stu);    }}
4、具体的运行结果及一些mybatis配置,在此省略,各位同学最好是自己去体会它们的不同哈