Spring-声明式事务
文章目录
目录
前言
大家好,今天给大家介绍一下spring-tx的相关内容
一 . 声明式事务概念
1.1 编程式事务
编程式事务指手动编写代码来管理事务,即通过编码的方式来控制事务的提交和回滚。
编程式事务的主要优点是灵活性高,可以按照自己的需求来控制事务的粒度、模式等等。但是,编写大量的事务控制代码容易出现问题,对代码的可读性和可维护性有一定影响。
Connection conn = ...;
try {
// 开启事务:关闭事务的自动提交
conn.setAutoCommit(false);
// 核心操作
// 业务代码
// 提交事务
conn.commit();
}catch(Exception e){
// 回滚事务
conn.rollBack();
}finally{
// 释放数据库连接
conn.close();
}
1.2 声明式事务
声明式事务是通过使用注解或配置文件的方式来实现事务管理的方式。在声明式事务中,开发人员只需要在需要进行事务管理的方法或类上添加相应的注解或配置,由事务管理框架来自动处理事务的开始、提交或回滚。这种方式使得代码更加简洁和易于维护,开发人员无需关注事务管理的细节,只需专注于业务逻辑的编写。
总的来说,编程式事务需要开发人员手动管理事务的细节,适用于对事务管理有较深了解且需要更细粒度控制的场景;而声明式事务通过注解或配置的方式来实现事务管理,减少了开发人员的工作量,适用于简单的事务管理场景。
1.3 spring事务管理器
spring声明式事务管理器对应接口
DataSourceTransactionManager类中的主要方法:
- doBegin():开启事务
- doSuspend():挂起事务
- doResume():恢复挂起的事务
- doCommit():提交事务
- doRollback():回滚事务
事务管理器是org.springframework.jdbc.datasource.DataSourceTransactionManager,将来整合 JDBC方式、JdbcTemplate方式、Mybatis方式的事务实现!
二 . 基于注解的声明式事务
Spring声明式事务管理常用的注解包括:
-
@Transactional:用于标记需要进行事务管理的方法或类。
-
@Propagation:用于设置事务的传播行为,包括REQUIRED(默认值)、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER、NESTED。
-
@ReadOnly:用于设置事务是否为只读事务,如果为只读事务,则不允许进行数据修改操作。
-
@RollbackFor:用于设置哪些异常需要回滚事务,可以设置多个异常类型。
-
@NoRollbackFor:用于设置哪些异常不需要回滚事务,可以设置多个异常类型。
事务属性: 只读
// readOnly = true把当前事务设置为只读 默认是false!
@Transactional(readOnly = true)
只读事务是指在事务执行期间,只能读取数据而不能对数据进行修改的事务。只读事务具有以下优势:
-
提升性能:只读事务不需要对数据进行修改操作,因此可以减少锁的竞争和冲突,提高并发性能。在高并发读取场景下,只读事务可以更好地满足性能需求。
-
减少资源占用:只读事务不需要对数据进行修改,因此不需要为数据的修改操作分配额外的资源,如日志记录、事务日志等。这样可以减少系统的资源占用,提高系统的吞吐量。
-
数据一致性:只读事务不会对数据进行修改,因此不会引起数据的不一致性。在某些场景下,只读事务可以提供数据的一致性视图,确保读取到的数据是一致的。
-
并发冲突减少:只读事务不会对数据进行修改,因此不会引起并发冲突。多个只读事务可以并发执行而不会互相干扰,提高系统的并发性能。
-
降低事务管理的复杂性:只读事务不需要关注事务的提交和回滚,只需要关注数据的读取逻辑。这样可以简化事务管理的复杂性,减少开发人员的工作量。
事务属性: 超时时间
事务在执行过程中,有可能因为遇到某些问题,导致程序卡住,从而长时间占用数据库资源。而长时间占用资源,大概率是因为程序运行出现了问题(可能是Java程序或MySQL数据库或网络连接等等)。
此时这个很可能出问题的程序应该被回滚,撤销它已做的操作,事务结束,把资源让出来,让其他正常程序可以执行。
概括来说就是一句话:超时回滚,释放资源。
事务属性: 事务异常
事务异常是在事务执行过程中发生的异常。事务异常可以分为两种情况:
-
运行时异常(unchecked exception):这些异常不需要在方法签名中声明,也不需要在事务配置中指定是否回滚。当发生运行时异常时,Spring默认会回滚事务。常见的运行时异常包括NullPointerException、ArrayIndexOutOfBoundsException、ClassCastException等。
-
受检异常(checked exception):这些异常需要在方法签名中声明,并且在事务配置中指定是否回滚。当发生受检异常时,可以根据需要选择是否回滚事务。如果不回滚事务,则异常会被捕获并处理,事务会继续执行。常见的受检异常包括IOException、SQLException等。
对于事务异常的处理,可以使用以下方式:
-
不进行事务回滚:可以通过在@Transactional注解中使用noRollbackFor属性指定不回滚的异常类型,或者在代码中捕获并处理异常,不抛出异常即可。
-
进行事务回滚:如果发生异常时需要回滚事务,可以通过在@Transactional注解中使用rollbackFor属性指定需要回滚的异常类型,或者在代码中抛出异常即可。
-
自定义异常处理:可以通过实现Spring的TransactionSynchronization接口,在事务提交或回滚时进行自定义的异常处理逻辑。
事务属性: 事务隔离级别
1. 事务隔离级别
数据库事务的隔离级别是指在多个事务并发执行时,数据库系统为了保证数据一致性所遵循的规定。常见的隔离级别包括:
1. 读未提交(Read Uncommitted):事务可以读取未被提交的数据,容易产生脏读、不可重复读和幻读等问题。实现简单但不太安全,一般不用。
2. 读已提交(Read Committed):事务只能读取已经提交的数据,可以避免脏读问题,但可能引发不可重复读和幻读。
3. 可重复读(Repeatable Read):在一个事务中,相同的查询将返回相同的结果集,不管其他事务对数据做了什么修改。可以避免脏读和不可重复读,但仍有幻读的问题。
4. 串行化(Serializable):最高的隔离级别,完全禁止了并发,只允许一个事务执行完毕之后才能执行另一个事务。可以避免以上所有问题,但效率较低,不适用于高并发场景。
不同的隔离级别适用于不同的场景,需要根据实际业务需求进行选择和调整。
2.事务隔离级别设置
在Spring中,可以使用@Transactional注解来设置事务隔离级别。@Transactional注解提供了一个isolation属性,用于设置事务的隔离级别。isolation属性可以设置为以下常量值之一:
-
Isolation.DEFAULT:使用数据库默认的隔离级别,通常为READ_COMMITTED。
-
Isolation.READ_UNCOMMITTED:读取未提交的数据,可以读取到其他事务未提交的数据,存在脏读、不可重复读和幻读的问题。
-
Isolation.READ_COMMITTED:读取已提交的数据,只能读取到已经提交的数据,可以避免脏读问题,但是仍然存在不可重复读和幻读的问题。
-
Isolation.REPEATABLE_READ(mysql默认):可重复读取数据,确保事务内多次读取同一数据时,结果始终相同,可以避免脏读和不可重复读问题,但仍然存在幻读问题。
-
Isolation.SERIALIZABLE:串行化读取数据,保证事务之间的隔离性最高,可以避免脏读、不可重复读和幻读问题,但是会降低并发性能。