Spring中的事务
@Transactional
注解是通过动态代理实现的如果你在方法中有try{}catch(Exception e){}处理,那么try里面的代码块就脱离了事务的管理,若要事务生效需要在catch中throw new RuntimeException (“xxxxxx”);这一点也是面试中会问到的事务失效的场景
事务的失效的场景:
- 在@Transactional注解的方法中,再调用本类中的其他方法method2时,那么method2方法上的@Transactional注解是不!会!生!效!的!但是加上也并不会报错。
- @Transactional注解的方法必须是公共方法,就是必须是public修饰符!!!
- 因为JVM的动态代理是基于接口实现的,通过代理类将目标方法进行增强,没有权限访问就无法进行增强
@Transactional
//@Transactional(propagation = Propagation.REQUIRES_NEW)//各自保持事务一致性
public static void method1(Map<String,Object> params){
System.out.println("入参数据:"+params);
method2(params);
System.out.println("结果数据:"+res);
}
@Transactional//不会生效
//@Transactional(propagation = Propagation.REQUIRES_NEW)//各自保持事务一致性
public static void method2(Map<String,Object> params){
System.out.println("入参数据:"+params);
String res = method2(params);
throw new RuntimeException("手动抛出异常。。。");
}
@Transactional
public static void main(){
Map<String,Object> params = new HashMap<String,Object>();
params.put("test","测试事务。。。");
method1(params);
method2(params);
}
小结:
- 只要方法
main
上有@Transactional
注解,并且方法method1
和方法method2
都处于当前(main)事务中,(不使用代理调用,方法method1
和方法method2
上的@Transactional
注解是不生效的;使用代理,需要方法method1
和方法method2
都处在main
方法的事务中,默认或者嵌套事务均可,当然也可以不加@Transactional
注解),那么便可以保持整体事务一致性。
@Transactional(propagation = Propagation.REQUIRES_NEW)//各自保持事务一致性
public static void method1(Map<String,Object> params){
System.out.println("入参数据:"+params);
method2(params);
System.out.println("结果数据:"+res);
}
@Transactional(propagation = Propagation.REQUIRES_NEW)//各自保持事务一致性
public static void method2(Map<String,Object> params){
System.out.println("入参数据:"+params);
String res = method2(params);
throw new RuntimeException("手动抛出异常。。。");
}
@Transactional
public static void main(){
Map<String,Object> params = new HashMap<String,Object>();
params.put("test","测试事务。。。");
method1(params);
method2(params);
}
- 要方法
method1
和方法method2
均单独保持事务一致性:如果不是用代理调用@Transactional
注解是不生效的,所以一定要使用代理调用实现,然后让方法method1
和方法method2
分别单独开启新的事务。- 在事务注解中使用
propagation = Propagation.REQUIRES_NEW
使事务保持单独一致性; @Transactional(propagation = Propagation.REQUIRES_NEW)
使方法各自保持事务一致性。- 或者在主方法(main)上不添加``@Transactional
注解,在各自方法上添加
@Transactional`注解来保持各自的事务独立性。
- 在事务注解中使用
@Transactional //各自保持事务一致性
public static void method1(Map<String,Object> params){
System.out.println("入参数据:"+params);
method2(params);
System.out.println("结果数据:"+res);
}
@Transactional //各自保持事务一致性
public static void method2(Map<String,Object> params){
System.out.println("入参数据:"+params);
String res = method2(params);
throw new RuntimeException("手动抛出异常。。。");
}
//不添加 @Transactional 事务注解
public static void main(){
Map<String,Object> params = new HashMap<String,Object>();
params.put("test","测试事务。。。");
method1(params);
method2(params);
}
小结:
- 1、就是@Transactional注解保证的是每个方法处在一个事务,如果有try一定在catch中抛出运行时异常。
@Transactional
public static void main(){
Map<String,Object> params = null;
try{
params.get("test");
}catch(Exception e){
throw new RuntimeException();
}
}
- 2、方法必须是public修饰符。否则注解不会生效,但是加了注解也没啥毛病,不会报错,只是不起作用。
@Transactional //使用private时该注解不起作用,必须为public才可
private static void main(){
Map<String,Object> params = null;
try{
params.get("test");
}catch(Exception e){
throw new RuntimeException();
}
}
- 3、this.本方法的调用,被调用方法上注解是不生效的,因为无法再次进行切面增强。
@Transactional//开启事务
public void main(){
Map<String,Object> params = new HashMap<String,Object>();
params.put("test","测试事务。。。");
this.method1(params);
}
@Transactional // 该事务不会生效
public void method1(Map<String,Object> params){
System.out.println("入参数据:"+params);
}
- 4、try{}中的代码块会脱离Spring的事务,想要事务生效必须要在catch(){}中抛出RuntimeException运行时异常。此时出现异常后,Spring会捕获回滚,来保证事务的一致性。在throw new RuntimeException(“抛出异常了”);之前代码均处于同一事物中,所有内容都会回滚,包括catch(){}中的方法代码也会回滚掉。