天天看点

@Transactional的使用

@Transactional什么时候开启事物

在使用注解事务的情况时,Spring会把每个方法的执行封装为AOP执行过程。

每次执行被事务注解方法时,会判断是否有必要创建事务。如果创建事务成功,则继续调用业务逻辑方法。

事务是在方法执行最开始阶段创建的,因此方法要越小越好。

用法

spring-servlet.xml

1.spring-servlet.xml中添加tx名字空间

xmlns:tx="http://www.springframework.org/schema/tx"

xmlns:aop="http://www.springframework.org/schema/aop"

xsi:schemaLocation="

http://www.springframework.org/schema/tx

http://www.springframework.org/schema/tx/spring-tx.xsd

方式1

<!-- transaction support-->

<!-- enable transaction annotation support -->

<tx:annotation-driven transaction-manager="txManager" />

<!-- PlatformTransactionMnager -->

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<property name="dataSource" ref="dataSource" />

</bean>

方式2

<!-- 配置事务管理器 -->

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dataSourceDefault">

<!-- 事务通知定义 -->

<tx:advice id="txAdvice" transaction-manager="transactionManager">

<tx:attributes>

<tx:method name="add" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />

<tx:method name="batchAdd" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />

<tx:method name="delete" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />

<tx:method name="update" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />

<tx:method name="batchUpdate" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />

<tx:method name="mergeToTrunk" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />

<tx:method name="addToTrunk" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />

</tx:attributes>

</tx:advice>

<!-- AOP切面配置 -->

<aop:config>

<aop:pointcut id="serviceMethod" expression="execution( com.suning.tpp.service..*(..))" />

<aop:advisor pointcut-ref="serviceMethod" advice-ref="txAdvice" />br/></aop:config>

测试代码

@Override

@Transactional(propagation = Propagation.NOT_SUPPORTED)

public ResourceBO detail(ResourceBO b) {

ExtPointTrunkBO extPointTrunkBO = new ExtPointTrunkBO();

String sysCode = "AIMP";

extPointTrunkBO.setTrunkVersion("1.3");

extPointTrunkBO.setSysCode(sysCode);

extPointTrunkBO.setVersion("1.4");

extPointTrunkService.add(extPointTrunkBO);

addExtPointImpl(sysCode);

int i = 1/0;

return super.detail(b);

}

// @Transactional(propagation = Propagation.MANDATORY)

public int addExtPointImpl(String sysCode) {

ExtPointImplTrunkBO extPointImplTrunkBO = new ExtPointImplTrunkBO();

extPointImplTrunkBO.setSysCode(sysCode);

extPointImplTrunkBO.setVersion("1.4");

extPointImplTrunkBO.setTrunkVersion("1.3");

return extPointImplTrunkService.add(extPointImplTrunkBO);

解释含义

以上面的调用关系detail调用addExtPointImpl方法

Spring事务传播属性:

1.propagation-required: 支持当前事务,如果有就加入当前事务中;如果当前方法没有事务,就新建一个事务;默认开启此方式

detail加此注解在Spring封装为AOP执行过程中,开启事物(新建一个事物);addExtPointImpl加此注解要看调用方是否开启事物了,

若开启了事物就加入前事务中,如果没开启从这里开始开启事物

2.propagation-supports: 支持当前事务,如果有就加入当前事务中;如果当前方法没有事务,就以非事务的方式执行;

detail加此注解在Spring封装为AOP执行过程中,以非事务的方式执行;addExtPointImpl加此注解要看调用方是否开启事物了,

若开启了事物就加入前事务中,如果没开启则以非事务的方式执行

3.propagation-mandatory: 支持当前事务,如果有就加入当前事务中;如果当前没有事务,就抛出异常;

detail加此注解,执行时报错No existing transaction found for transaction marked with propagation 'mandatory';

addExtPointImpl加此注解要看调用方是否开启事物了,若开启了事物就加入前事务中,如果没开启则抛出异常

4.propagation-requires_new: 新建事务,如果当前存在事务,就把当前事务挂起;如果当前方法没有事务,就新建事务;

5.propagation-not-supported: 以非事务方式执行,如果当前方法存在事务就挂起当前事务;如果当前方法不存在事务,就以非事务方式执行;

6.propagation-never: 以非事务方式执行,如果当前方法存在事务就抛出异常;如果当前方法不存在事务,就以非事务方式执行;

7.propagation-nested: 如果当前方法有事务,则在嵌套事务内执行;如果当前方法没有事务,则与required操作类似;

关于事务挂起的举例:(某事务挂起之后,任何操作都不在该事务的控制之下)

例如: 方法A支持事务,方法B不支持事务。 即PROPAGATION_NOT_SUPPORTED

方法A调用方法B。

在方法A开始运行时,系统为它建立Transaction,方法A中对于数据库的处理操作,会在该Transaction的控制之下。

这时,方法A调用方法B,方法A打开的 Transaction将挂起,方法B中任何数据库操作,都不在该Transaction的管理之下。

当方法B返回,方法A继续运行,之前的Transaction回复,后面的数据库操作继续在该Transaction的控制之下 提交或回滚。

继续阅读