概述
spring-transactional
案例简介
本案例主要用于深入了解 Spring 的事务注解@Transactional
。
@Transactional 特性
@Transactional
注解只能应用到 public 修饰符上,对其他修饰符不起作用,但不报错。@Transactional
一般加到实现类或实现类方法上,不要加到接口或接口方法上。@Transactional
仅仅对 unchecked 异常进行事务异常回滚;如果是 checked 异常则不进行异常回滚。- unchecked 异常一般为错误或运行时异常
- Error:Throwable 的子类。著名的 VirtualMachineError 是 Error 的子类之一,VirtualMachineError 还有 StackOverflowError、OutOfMemoryError 等子类。
- RuntimeException:Exception 的子类,而 Exception 同样是 Throwable 的子类。RuntimeException 下面包括 NPE,ClassCastException,ArithmaticException 等异常,这些错误的特点是不用被显式地抛出或捕获,开发者通过仔细检查代码可以避免这些异常。
- checked 异常则为编译过程中的异常
- 其他 Exception:除了 RuntimeException 之外其他的 Exception 的子类,包括 FileNotFoundException,IOException,SQLException 等,这些异常的特点是必须被代码抛出或捕获,否则编译都无法通过。
- unchecked 异常一般为错误或运行时异常
@Transactional 有效场景
-
正常执行写操作
@Override @Transactional public int updateById(Employee employee, Integer empId) { return employeeMapper.updateById(employee, empId); }
-
unchecked 异常
-
RuntimeException
@Override @Transactional public int updateByIdRuntimeException(Employee employee, Integer empId) { int effect = employeeMapper.updateById(employee, empId); System.out.println(1 / 0); return effect;
-
}
```
调用此方法,在执行此方法的语句`System.out.println(1 / 0);`时会抛出运行时异常中的算术异常(ArithmaticException),事务会回滚,数据库中的数据不会被改变。
-
OutOfMemoryError
写一个类来制造堆内存溢出
public class HeapOOM { static class OOMObject { } public static void mockHeapOOM() { List<Object> objects = new ArrayList<>(); while (true) { objects.add(new OOMObject()); } } }
可以调用此类的静态方法
mockHeapOOM
不停地创建OOMObject
对象并将其添加至数组中,而被数组强引用的对象无法被 GC 回收,堆内存很快被消耗完毕。@Override @Transactional public int updateByIdOOM(Employee employee, Integer empId) { int effect = employeeMapper.updateById(employee, empId); HeapOOM.mockHeapOOM(); return effect; }
打开 IntelliJ IDEA 的 Edit Configuration,在 VM Options 一栏为调用
updateByIdOOM
方法的单元测试配置好 JVM 参数。-ea -Xmx10m -Xms5m -XX:+HeapDumpOnOutOfMemoryError
-ea
可以打开断言机制-Xmx10m -Xms5m
表示堆最大可用值是 10M,堆初始值为 5M-XX:+HeapDumpOnOutOfMemoryError
打印堆溢出报错信息
运行单元测试方法,控制台中报如下错误信息:
java.lang.OutOfMemoryError: GC overhead limit exceeded
查看数据库,数据没有被改变,所以此时事务正常回滚。
@Transactional 无效场景
-
checked 异常
@Override @Transactional public void updateByIdException(Employee employee, Integer empId) throws IOException { employeeMapper.updateById(employee, empId); throw new IOException("模拟 IO 错误"); }
调用此方法,会在
throw new IOException("模拟 IO 错误")
时抛出模拟的错误,但是事务并不回滚,数据库中的数据发生了改变。这是因为 IOException 属于 checked 异常,@Transactional
默认情况下不对 checked 异常进行事务回滚。此时,想要在抛出 checked 异常时进行事务回滚,需要在@Transactional
后面配置上rollBackFor
属性:@Override @Transactional(rollbackFor = IOException.class) public void updateByIdException(Employee employee, Integer empId) throws IOException { employeeMapper.updateById(employee, empId); throw new IOException("模拟 IO 错误"); }
这里配置为
rollbackFor = Exception.class
可以。 -
被没有事务控制的方法调用
如果带有
@Transactional
的方法 A 被另一个不带有@Transactional
的方法 B 调用,那么调用 B 时 A 的@Transactional
也会失效。@Override @Transactional public int updateByIdRuntimeException(Employee employee, Integer empId) { int effect = employeeMapper.updateById(employee, empId); System.out.println(1 / 0); return effect; } @Override public int updateByIdWithoutTransactional(Employee employee, Integer empId) { return updateByIdRuntimeException(employee, empId); }
此时,调用
updateByIdWithoutTransactional
,数据库的数据会被改变,这是由于事务不会因为在updateByIdRuntimeException
中抛出ArithmaticException
而回滚。
最后
以上就是幸福啤酒为你收集整理的spring-transactional初步了解spring-transactional的全部内容,希望文章能够帮你解决spring-transactional初步了解spring-transactional所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复