Spring事务——针对实习面试
目录
- Spring事务
- 事务的基本概念
- Spring管理事务的方式有几种?
- Spring事务中有哪几种事务传播行为?
- Spring事务中的隔离级别有哪几种?
- Spring事务如何回滚的?
- @Transactional注解有什么用?
Spring事务
事务的基本概念
在Spring框架中,事务的基本概念主要围绕以下几个核心概念:
-
事务(Transaction):
- 事务是数据库操作的逻辑单位,它由一系列数据库操作组成,这些操作要么全部成功,要么全部失败。事务保证了数据的完整性和一致性。
-
事务属性(Transaction Attributes):
- 事务属性定义了事务的隔离级别、传播行为、超时设置、只读标志和回滚规则等。这些属性决定了事务应该如何被管理。
-
事务管理器(Transaction Manager):
- 事务管理器负责管理事务的整个生命周期,包括开启事务、提交事务和回滚事务。Spring提供了多种事务管理器的实现,如
DataSourceTransactionManager
、HibernateTransactionManager
等。
- 事务管理器负责管理事务的整个生命周期,包括开启事务、提交事务和回滚事务。Spring提供了多种事务管理器的实现,如
-
事务隔离级别(Transaction Isolation Level):
- 隔离级别定义了事务之间的隔离程度,防止事务操作的数据被其他事务干扰。常见的隔离级别包括:READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ和SERIALIZABLE。
-
事务传播行为(Transaction Propagation Behavior):
- 传播行为定义了当现有事务存在时,新事务应该如何被处理。Spring定义了多种传播行为,如REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER和NESTED。
-
声明式事务管理(Declarative Transaction Management):
- 声明式事务管理使用Spring的AOP功能,通过在方法上添加
@Transactional
注解来声明事务属性,这种方式使得事务管理更加声明化和简洁。
- 声明式事务管理使用Spring的AOP功能,通过在方法上添加
-
编程式事务管理(Programmatic Transaction Management):
- 编程式事务管理通过编码的方式直接使用
PlatformTransactionManager
接口来控制事务。这种方式更加灵活,但代码侵入性较强。
- 编程式事务管理通过编码的方式直接使用
-
回滚规则(Rollback Rules):
- 回滚规则定义了哪些异常会导致事务回滚。Spring默认的规则是运行时异常(
RuntimeException
及其子类)和Error
会导致事务回滚,而检查型异常(checked exceptions)默认不回滚。
- 回滚规则定义了哪些异常会导致事务回滚。Spring默认的规则是运行时异常(
-
事务超时(Transaction Timeout):
- 事务超时定义了事务可以运行的最长时间。如果事务运行时间超过这个时间限制,数据库将自动回滚事务。
-
事务的ACID属性:
- 原子性(Atomicity):事务中的所有操作要么全部完成,要么全部不完成。
- 一致性(Consistency):事务必须保证数据库从一个一致性状态转变到另一个一致性状态。
- 隔离性(Isolation):事务之间的操作是相互隔离的,一个事务的操作不能被其他事务干扰。
- 持久性(Durability):一旦事务提交,它对数据库的修改就是永久性的,即使系统发生故障也不会丢失。
这些概念构成了Spring事务管理的基础,理解这些概念有助于更好地使用Spring框架进行事务管理。
Spring管理事务的方式有几种?
Spring框架提供了两种主要的方式来管理事务:
-
声明式事务管理(Declarative Transaction Management):
- 这是Spring推荐的方式,通过在代码中添加注解或在配置文件中使用XML标签来声明事务的边界和属性。声明式事务管理又分为两种形式:
- 基于注解的方式:在方法上使用
@Transactional
注解来声明事务。这种方式简单直观,是最常用的声明式事务管理方式。 - 基于XML配置的方式:在Spring的配置文件中使用
<tx:*>
标签来定义事务属性和切面(AOP),从而管理事务。
- 基于注解的方式:在方法上使用
- 这是Spring推荐的方式,通过在代码中添加注解或在配置文件中使用XML标签来声明事务的边界和属性。声明式事务管理又分为两种形式:
-
编程式事务管理(Programmatic Transaction Management):
- 这种方式通过编程的方式直接使用Spring的
PlatformTransactionManager
接口来管理事务。编程式事务管理提供了更高的灵活性,但代码侵入性较强,需要手动管理事务的开启、提交和回滚。 - 编程式事务管理通常使用
TransactionTemplate
或直接通过PlatformTransactionManager
来实现。
- 这种方式通过编程的方式直接使用Spring的
这两种方式各有优缺点,声明式事务管理因其简单和非侵入性而更受欢迎,而编程式事务管理则在需要更细粒度控制事务时更为适用。在实际开发中,可以根据具体需求和场景选择适合的事务管理方式。
Spring事务中有哪几种事务传播行为?
Spring事务管理中定义了七种事务传播行为,这些行为通过PropagationBehavior
枚举在TransactionDefinition
接口中定义。以下是每种事务传播行为的详细说明:
-
PROPAGATION_REQUIRED:
- 如果当前存在事务,则加入该事务;如果当前没有事务,就新建一个事务。这是最常见的传播行为。
-
PROPAGATION_SUPPORTS:
- 如果当前存在事务,就加入该事务;如果当前没有事务,就以非事务方式执行。
-
PROPAGATION_MANDATORY:
- 如果当前存在事务,则加入该事务;如果当前没有事务,就抛出异常。
-
PROPAGATION_REQUIRES_NEW:
- 总是新建事务,如果当前存在事务,就把当前事务挂起。
-
PROPAGATION_NOT_SUPPORTED:
- 总是非事务地执行,如果当前存在事务,就把当前事务挂起。
-
PROPAGATION_NEVER:
- 总是非事务地执行,如果当前存在事务,就抛出异常。
-
PROPAGATION_NESTED:
- 如果当前存在事务,则在当前事务内新建一个事务(嵌套事务)。如果当前没有事务,就新建一个事务。嵌套事务需要事务管理器支持嵌套事务。
这些传播行为允许开发者根据不同的业务需求来控制事务的边界和行为,从而实现灵活的事务管理。
Spring事务中的隔离级别有哪几种?
Spring事务中的隔离级别对应于数据库事务的隔离级别,用于定义事务在并发环境下如何可见和交互。Spring支持以下五种隔离级别:
-
ISOLATION_DEFAULT:
- 使用底层数据库的默认隔离级别,通常在大多数数据库中是
READ_COMMITTED
。
- 使用底层数据库的默认隔离级别,通常在大多数数据库中是
-
ISOLATION_READ_UNCOMMITTED:
- 最低的隔离级别,允许读取未提交的数据,可能会导致脏读、不可重复读和幻读。
-
ISOLATION_READ_COMMITTED:
- 保证可以读取到其他事务提交的数据,可以避免脏读,但仍有可能出现不可重复读和幻读。
-
ISOLATION_REPEATABLE_READ:
- 保证在一个事务中多次读取同样的记录结果是一致的,除非数据是被本事务自己修改的,可以避免脏读和不可重复读,但幻读仍有可能发生。
-
ISOLATION_SERIALIZABLE:
- 最高的隔离级别,完全串行化的事务,可以避免脏读、不可重复读和幻读,但会牺牲系统的并发性能。
隔离级别的选择取决于具体的业务需求和性能考量。较高的隔离级别可以提供更好的数据一致性保证,但可能会降低系统的并发性能。在实际应用中,需要根据业务场景和性能测试结果来选择合适的隔离级别。
Spring事务如何回滚的?
Spring事务的回滚主要通过以下两种方式实现:
-
自动回滚:
- 在声明式事务管理中,Spring默认的策略是当事务中的方法抛出了运行时异常(
RuntimeException
及其子类)或者Error
时,事务会自动回滚。对于检查型异常(checked exceptions),Spring默认不回滚事务,除非你在@Transactional
注解中通过rollbackFor
属性明确指定了哪些异常需要回滚。
例如:
@Transactional(rollbackFor = CustomException.class) public void someServiceMethod() { // ... }
在这个例子中,如果
someServiceMethod
方法抛出了CustomException
异常,Spring事务管理器会自动回滚事务。 - 在声明式事务管理中,Spring默认的策略是当事务中的方法抛出了运行时异常(
-
手动回滚:
- 在编程式事务管理中,你可以使用
TransactionStatus
对象来手动控制事务的回滚。TransactionStatus
对象可以通过TransactionTemplate
的execute
方法或者PlatformTransactionManager
的getTransaction
方法获得。
例如,使用
TransactionTemplate
:TransactionTemplate template = new TransactionTemplate(transactionManager); template.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { // ... if (需要回滚) { status.setRollbackOnly(); } } });
在这个例子中,如果
doInTransactionWithoutResult
方法中的逻辑判断需要回滚事务,可以调用status.setRollbackOnly()
方法来标记事务为回滚状态。或者,如果你直接使用
PlatformTransactionManager
:public void someServiceMethod() { DefaultTransactionDefinition def = new DefaultTransactionDefinition(); // 设置事务属性 TransactionStatus status = transactionManager.getTransaction(def); try { // ... } catch (Exception e) { transactionManager.rollback(status); } finally { if (需要回滚) { transactionManager.rollback(status); } } }
在这个例子中,如果需要回滚事务,可以直接调用
transactionManager.rollback(status)
方法。 - 在编程式事务管理中,你可以使用
这两种方式提供了灵活的事务回滚控制,可以根据具体的业务逻辑和异常处理需求来决定是否回滚事务。
@Transactional注解有什么用?
@Transactional
注解是Spring框架提供的一种声明式事务管理的方式,它用于方法上,以表明该方法应该在一个事务的上下文中执行。使用@Transactional
注解可以简化事务管理的复杂性,使得业务代码更加简洁和清晰。以下是@Transactional
注解的一些主要用途和特点:
-
声明事务边界:
- 通过在方法上添加
@Transactional
注解,可以指定哪些方法应该在事务的上下文中执行,从而定义了事务的开始和结束点。
- 通过在方法上添加
-
自动管理事务:
- Spring会自动管理这些方法的事务,包括事务的开启、提交和回滚。这意味着开发者不需要手动编写代码来管理事务的这些细节。
-
配置事务属性:
@Transactional
注解允许你配置事务的各种属性,如隔离级别、传播行为、超时时间、只读标志和回滚规则等。
-
异常驱动的回滚:
- 默认情况下,如果方法执行过程中抛出了运行时异常(
RuntimeException
及其子类)或Error
,事务将会自动回滚。你也可以通过rollbackFor
属性指定其他需要回滚的异常类型。
- 默认情况下,如果方法执行过程中抛出了运行时异常(
-
非异常回滚:
- 可以通过
noRollbackFor
属性指定不会导致事务回滚的异常类型。
- 可以通过
-
事务传播行为:
- 通过
propagation
属性,可以定义方法的事务传播行为,例如是否应该加入现有的事务或创建一个新的事务。
- 通过
-
事务超时和只读:
- 可以通过
timeout
属性设置事务的超时时间,以及通过readOnly
属性指定事务是否为只读事务。
- 可以通过
-
简化代码:
- 使用
@Transactional
注解可以避免在业务逻辑代码中混入事务管理代码,使得代码更加专注于业务逻辑本身。
- 使用
-
AOP支持:
@Transactional
注解是基于Spring AOP实现的,这意味着它可以通过切面来增强方法的执行,而不需要修改方法的实现。
-
灵活性和可重用性:
- 由于
@Transactional
注解是声明在方法层面的,因此它非常灵活,可以应用于任意需要事务管理的方法上,并且可以轻松地在不同的类或方法之间重用。
- 由于
总的来说,@Transactional
注解提供了一种简单而强大的方式来管理事务,使得开发者可以更加专注于业务逻辑的实现,而不是事务的管理细节。