Spring笔记12 基于XML和注解的事务控制
coconutnut

https://www.bilibili.com/video/av47952931
p72-74

基于XML的事务控制

2个工具类:ConnectionUtils 和 TransactionManager

Spring笔记09 事务控制的问题&动态代理

主要配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!-- 配置Connection的工具类 ConnectionUtils -->
<bean id="connectionUtils" class="com.itheima.utils.ConnectionUtils">
<!-- 注入数据源-->
<property name="dataSource" ref="dataSource"></property>
</bean>

<!-- 配置事务管理器-->
<bean id="txManager" class="com.itheima.utils.TransactionManager">
<!-- 注入ConnectionUtils -->
<property name="connectionUtils" ref="connectionUtils"></property>
</bean>

<!--配置aop-->
<aop:config>
<!--配置通用切入点表达式-->
<aop:pointcut id="pt1" expression="execution(* com.itheima.service.impl.*.*(..))"></aop:pointcut>
<aop:aspect id="txAdvice" ref="txManager">
<!--配置前置通知:开启事务-->
<aop:before method="beginTransaction" pointcut-ref="pt1"></aop:before>
<!--配置后置通知:提交事务-->
<aop:after-returning method="commit" pointcut-ref="pt1"></aop:after-returning>
<!--配置异常通知:回滚事务-->
<aop:after-throwing method="rollback" pointcut-ref="pt1"></aop:after-throwing>
<!--配置最终通知:释放连接-->
<aop:after method="release" pointcut-ref="pt1"></aop:after>
</aop:aspect>
</aop:config>

基于注解的AOP配置

xml中要开启对注解的支持

1
2
3
4
5
6
7
8
9
@Service("accountService")
public class AccountServiceImpl implements IAccountService{

@Autowired
private IAccountDao accountDao;

// ...

}
1
2
3
4
5
6
7
8
9
10
11
12
@Repository("accountDao")
public class AccountDaoImpl implements IAccountDao {

@Autowired
private QueryRunner runner;

@Autowired
private ConnectionUtils connectionUtils;

// ...

}
1
2
3
4
5
6
7
8
9
@Component("connectionUtils")
public class ConnectionUtils {

@Autowired
private DataSource dataSource;

// ...

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
@Component("txManager")
@Aspect
public class TransactionManager {

@Autowired
private ConnectionUtils connectionUtils;

@Pointcut("execution(* com.itheima.service.impl.*.*(..))")
private void pt1(){}

@Around("pt1()")
public Object aroundAdvice(ProceedingJoinPoint pjp){
Object rtValue = null;
try {
// 1.获取参数
Object[] args = pjp.getArgs();
// 2.开启事务
this.beginTransaction();
// 3.执行方法
rtValue = pjp.proceed(args);
// 4.提交事务
this.commit();

// 返回结果
return rtValue;

}catch (Throwable e){
// 5.回滚事务
this.rollback();
throw new RuntimeException(e);
}finally {
// 6.释放资源
this.release();
}
}

}

如果分别在开启事务、提交事务、回滚事务、释放连接的函数上分别加@Before(“pt1()”)、@AfterReturning(“pt1()”)、@AfterThrowing(“pt1()”)、@After(“pt1()”)

理论上没毛病。但是!Spring实际的执行顺序是有问题的(同 见笔记9)

最终通知在后置通知之前执行了,于是根本没有提交就释放了,连接已经变成了新的连接

所以不要分别用。用一个环绕通知,里面try-catch,自己控制顺序