一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第26天,点击查看活动详情。
xml方式实现
①配置事务管理器
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
②配置事务切面
<!--定义事务管理的通知类-->
<tx:advice transaction-manager="txManager" id="txAdvice">
<tx:attributes>
<tx:method name="trans*"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="pt" expression="execution(* com.springstudy.service..*.*(..))"></aop:pointcut> <aop:advisor advice-ref="txAdvice" pointcut-ref="pt">
</aop:advisor>
</aop:config>
注意,因为声明式事务底层是通过AOP实现的,所以最好把AOP相关依赖都加上。
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
属性配置
事务传播行为propagation
当事务方法嵌套调用时,需要控制是否开启新事务,可以使用事务传播行为来控制。
测试案例:
@Servicepublic
class TestServiceImpl {
@Autowired
AccountService accountService;
@Transactional
public void test(){
accountService.transfer(1,2,10D);
accountService.log(); }}
public class AccountServiceImpl implements AccountService {
//...省略其他不相关代码
@Transactional
public void log() {
System.out.println("打印日志");
int i = 1/0; 如果日志里面报错,转账也就回滚
}}
| 属性值 | 行为 |
|---|---|
| REQUIRED(必须要有) | 外层方法有事务,内层方法就加入。外层没有,内层就新建 |
| REQUIRES_NEW(必须要有新事务) | 外层方法有事务,内层方法新建。外层没有,内层也新建 |
| SUPPORTS(支持有) | 外层方法有事务,内层方法就加入。外层没有,内层就也没有 |
| NOT_SUPPORTED(支持没有) | 外层方法有事务,内层方法没有。外层没有,内层也没有 |
| MANDATORY(强制要求外层有) | 外层方法有事务,内层方法加入。外层没有。内层就报错 |
| NEVER(绝不允许有) | 外层方法有事务,内层方法就报错。外层没有。内层就也没有 |
例如:
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void transfer(Integer outId, Integer inId, Double money) {
//增加
accoutDao.updateMoney(inId,money);
//减少
accoutDao.updateMoney(outId,-money);
}
3.3.2 隔离级别isolation
Isolation.DEFAULT 使用数据库默认隔离级别
Isolation.READ_UNCOMMITTED
Isolation.READ_COMMITTED
Isolation.REPEATABLE_READ
Isolation.SERIALIZABLE
@Transactional(propagation = Propagation.REQUIRES_NEW,isolation = Isolation.READ_COMMITTED)
public void transfer(Integer outId, Integer inId, Double money) {
//增加
accoutDao.updateMoney(inId,money);
//减少
accoutDao.updateMoney(outId,-money); }
3.3.3 只读readOnly
如果事务中的操作都是读操作,没涉及到对数据的写操作可以设置readOnly为true。这样可以提高效率。
@Transactional(readOnly = true)
public void log() {
System.out.println("打印日志");
int i = 1/0;
}