@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的控制之下 提交或回滚。