java_微服务03SpringBoot常见问题

参考教程:
Spring Boot 2.x基础教程:https://blog.didispace.com/spring-boot-learning-2x/
Spring Boot:https://blog.didispace.com/categories/Spring-Boot/

事务

事务不生效的原因

常见情况
01、数据库引擎不支持事务
02、异常被你的 catch“吃了”导致@Transactional失效
03、@Transactional 应用在非 public 修饰的方法上
04、同一个类中方法调用,导致@Transactional失效
开发中避免不了会对同一个类里面的方法调用,比如有一个类Test,它的一个方法A,A再调用本类的方法B(不论方法B是用public还是private修饰),但方法A没有声明注解事务,而B方法有。则外部调用方法A之后,方法B的事务是不会起作用的。这也是经常犯错误的一个地方。
那为啥会出现这种情况?其实这还是由于使用Spring AOP代理造成的,因为只有当事务方法被当前类以外的代码调用时,才会由Spring生成的代理对象来管理。
05、@Transactional 注解属性 propagation 设置错误
这种失效是由于配置错误,若是错误的配置以下三种 propagation,事务将不会发生回滚。
TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。 TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。 TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
06,@Transactional 注解属性 rollbackFor 设置错误
rollbackFor 可以指定能够触发事务回滚的异常类型。Spring默认抛出了未检查unchecked异常(继承自 RuntimeException 的异常)或者 Error才回滚事务;其他异常不会触发回滚事务。如果在事务中抛出其他类型的异常,但却期望 Spring 能够回滚事务,就需要指定 rollbackFor属性。

@Transactional 应该加到什么地方,如果加到Controller会回滚吗?

@Transactional 加到Controller层也是生效的,但是为了规范起见,还是加到service层上。

@Transactional 注解中用不用加rollbackFor = Exception.class 这个属性值

默认情况下,当程序发生 RuntimeException 和 Error 的这两种异常的时候事务会回滚,但是如果发生了checkedExcetions ,如fileNotfundException 则不会回滚,所以 rollbackFor = Exception.class 这个一定要加!

为什么catch了异常,但事务还是回滚

事务调用嵌套问题具体结果如下代码:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/**
* 同类中在方法a中调用b
* a没有事务,b有 ,异常发生在b中 不会回滚
*/
@RequestMapping("/a1")
public void a1(){
transactionalService.a1();
}

/**
* 同类中在方法a中调用b
* a没有事务,b有 ,异常发生在a中 不会回滚
*/
@RequestMapping("/a2")
public void a2(){
transactionalService.a2();
}
/**
* 同类中在方法a中调用b
* a有事务,b没有 ,异常发生在b中 会回滚
*/
@RequestMapping("/a3")
public void a3(){
transactionalService.a3();
}
/**
* 同类中在方法a中调用b
* a有事务,b没有 ,异常发生在a中 会回滚
*/
@RequestMapping("/a4")
public void a4(){
transactionalService.a4();
}
/**
* 同类中在方法a中调用b
* a有事务,b也有 ,异常发生在b中 会回滚
*/
@RequestMapping("/a5")
public void a5(){
transactionalService.a5();
}
/**
* 同类中在方法a中调用b
* a有事务,b也有 ,异常发生在a中 会回滚
*/
@RequestMapping("/a6")
public void a6(){
transactionalService.a6();
}


/**
*a类中调用b类中的方法
* a中有事务,b中也有 会回滚
*
*/
@RequestMapping("/b5")
public void b5(){
transactionalService.b5();
}

/**
*a类中调用b类中的方法
* a中有事务,b中没有 会回滚
*
*/
@RequestMapping("/b6")
public void b6(){
transactionalService.b6();
}

/**
*a类中调用b类中的方法
* a没有事务,b中有 不会回滚
*
*/
@RequestMapping("/b7")
public void b7(){
transactionalService.b7();
}

/**
*a类中调用b类中的方法
* a没有事务,b中没有 不会回滚
*
*/
@RequestMapping("/b8")
public void b8(){
transactionalService.b8();
}

总结:如果在a方法中调用b方法不管是不是a和b是不是在同一个类中,只要a方法中没有事务,则发生异常的时候不会回滚,即:当a无事务时,则a和b均没有事务,当a有事务时,b如果有事务,则b事务会加到a事务中,二者为同一事务!

总结

springboot中默认是开启事务的,在service层的方法加上@Transactional(rollbackFor = Exception.class) 注解即可实现事务 如果在方法a中调用方法b 如果要实现事务,则只需要在方法上加上@Transactional(rollbackFor = Exception.class) 即可!
如果业务需要,一定要抛出checked异常的话,可以通过rollbackFor属性指定异常类型即可。

JTA实现多数据源的事务管理

使用JTA实现多数据源的事务管理:https://blog.didispace.com/spring-boot-learning-24-3-12/
在Spring Boot 2.x中,整合了这两个JTA的实现:
Atomikos:可以通过引入spring-boot-starter-jta-atomikos依赖来使用
Bitronix:可以通过引入spring-boot-starter-jta-bitronix依赖来使用

Async实现异步调用

Spring Boot使用@Async实现异步调用:使用Future以及定义超时:https://blog.didispace.com/springbootasync-4/
Spring Boot使用@Async实现异步调用:ThreadPoolTaskScheduler线程池的优雅关闭:https://blog.didispace.com/springbootasync-3/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Bean("taskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskScheduler executor = new ThreadPoolTaskScheduler();
executor.setPoolSize(20);
executor.setThreadNamePrefix("taskExecutor-");
return executor;
}

@Async("taskExecutor")
public void doTaskOne() throws Exception {
log.info("开始做任务一");
long start = System.currentTimeMillis();
log.info(stringRedisTemplate.randomKey());
long end = System.currentTimeMillis();
log.info("完成任务一,耗时:" + (end - start) + "毫秒");
}

加密配置中的敏感信息

Spring Boot 2.x基础教程:加密配置中的敏感信息:https://blog.didispace.com/spring-boot-learning-2-1-5/

MyBatis的多数据源

Spring Boot 2.x基础教程:MyBatis的多数据源配置:https://blog.didispace.com/spring-boot-learning-21-3-9/

参考

为什么catch了异常,但事务还是回滚了?:https://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ%3D%3D&idx=2&mid=2247535985&sn=71f31a9e35843aa0c82402780fdc9cb8
spring声明式事务 @Transactional 不回滚的多种情况以及解决方案:https://blog.csdn.net/weter_drop/article/details/103582742
为什么加了@Transactional注解,事务没有回滚?:https://blog.didispace.com/transactional-not-rollback/
使用事务(@Transactional)可能出现的问题:https://blog.csdn.net/zero__007/article/details/112046592#t5

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×