前言:
博主在最近的几次面试中,大中小厂都问到了Spring的事务相关问题,这块知识确实是面试中的重点内容,因此结合所看的书籍,在这篇文章中总结下。该专栏比较适合刚入坑Java的小白以及准备秋招的大佬阅读,感谢大佬的关注。
如果文章有什么需要改进的地方欢迎大佬提出,对大佬有帮助希望可以支持下哦~
小威在此先感谢各位小伙伴儿了😁
以下正文开始
文章目录
Spring事务包括声明式事务管理和注解式事务管理,我们通过概念和小demo的形式一步一步地来一起学习这个知识点!
声明式事务管理
首先简单介绍下Spring的声明式事务管理:
声明式事务管理是指通过配置来实现事务管理,我们只需定义事务边界和事务属性,不需要显式编写事务管理的代码。
那么我们如何实现呢?
首先配置事务管理器和数据源:通过配置
<bean>
元素,使用 TransactionManager 类型的 Bean 来提供事务管理器的实例,并使用 DataSource 类型的 Bean 来提供数据源。
接着定义事务边界:使用
<tx:advice>
元素来定义事务边界和事务属性,指定哪些方法需要进行事务管理。
还需要配置事务通知:使用
<aop:config>
元素来启用事务管理功能并将事务通知应用到指定的切入点上。
理论知识先讲到这里,储备这些知识可以和面试官进行交流~
注解式管理事务
除了上面提到的声明式管理之外,Spring提供了一种更加简单且强大的方式来管理事务,通过使用注解式事务,可以在方法级别上进行声明和配置事务的行为。这块面试官问的更多,我们来详细介绍下:
@Transactional注解(核心注解): @Transactional是Spring中最常用的注解之一,用于标识需要进行事务管理的方法或类。它可以应用在方法上或类上,而且还可以配置这些属性:
- value:指定事务管理器的名称(如果有多个事务管理器)。
- propagation:指定事务传播行为,默认值为REQUIRED。
- isolation:指定事务隔离级别,默认值为DEFAULT。
- readOnly:指定事务是否为只读事务,默认值为false。
- timeout:指定事务超时时间,默认值为-1,表示不设置超时。
事务传播行为
上面介绍了Spring实现事务的两种方式,接下来介绍下另一个重量级的知识点–》事务传播行为。
事务传播行为定义了当一个事务方法调用另一个事务方法时,如何处理事务的范围。Spring提供了多种传播行为选项,包括:
- REQUIRED:如果当前没有事务,则创建一个新的事务;如果已存在事务,则加入到当前事务中。
- REQUIRES_NEW:每次都会创建一个新的事务,如果已存在事务则将其挂起。
- SUPPORTS:如果当前存在事务,则加入到当前事务中;如果没有事务,则以非事务方式执行。
- NOT_SUPPORTED:以非事务方式执行方法,如果当前存在事务则将其挂起。
- NEVER:以非事务方式执行方法,如果当前存在事务则抛出异常。
- MANDATORY:如果当前存在事务,则加入到当前事务中;如果没有事务,则抛出异常。
- NESTED:如果当前存在事务,则将该事务嵌套到当前事务中作为一个保存点,可以回滚到该保存点。
事务隔离级别
接下来介绍下 spring的事务隔离级别,这一块也是面试官经常问到的一点。它与数据库的事务隔离级别有着异曲同工之妙。
事务隔离级别定义了多个事务同时运行时彼此之间的可见性和影响范围。Spring支持以下事务隔离级别:
- DEFAULT:使用数据库默认的事务隔离级别。
- READ_UNCOMMITTED:最低级别的隔离级别,允许读取未提交的数据。
- READ_COMMITTED:允许读取已提交的数据。
- REPEATABLE_READ:对同一数据的多次读取结果保持一致,避免脏读和不可重复读。
- SERIALIZABLE:最高级别的隔离级别,确保事务串行执行,避免任何并发问题。
- 只读事务(readOnly): 如果一个事务中的方法仅执行读操作而不进行写操作时,可以将事务标记为只读事务。这样做可以提高性能,因为只读事务不需要对数据进行锁定。
学生管理系统demo
如果上面的概念看着有点懵,那么接下来让我们通过一个学生管理系统的demo来详细介绍 Spring 的声明式事务和基于注解的事务管理。
我从项目中扒出来部分伪代码,现在我们有一个简单的学生管理系统,其中包含两个服务方法:
addStudent()
和
updateStudent()
。addStudent() 方法用于添加学生信息,updateStudent() 方法用于更新学生信息。
使用声明式事务管理demo
前面概念部分提到过,在声明式事务管理中,我们可以使用 XML 配置来定义事务边界和事务特性。
首先,我们需要配置事务管理器和数据源。在 Spring 配置文件中,我们可以使用 TransactionManager 元素和 DataSource 元素来配置相应的 Bean。
<beanid="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><propertyname="dataSource"ref="dataSource"/></bean><beanid="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource"><!-- 数据源配置 --></bean>
接下来,定义事务边界,我们可以在服务类中使用 :
<beanid="studentService"class="com.test.StudentService"><!-- 依赖注入 --></bean><tx:adviceid="txAdvice"transaction-manager="transactionManager"><tx:attributes><tx:methodname="add*"propagation="REQUIRED"/><tx:methodname="update*"propagation="REQUIRED"/></tx:attributes></tx:advice><aop:config><aop:pointcutid="studentServicePointcut"expression="execution(* com.example.StudentService.*(..))"/><aop:advisoradvice-ref="txAdvice"pointcut-ref="studentServicePointcut"/></aop:config>
在上面的代码中,我们使用了
<tx:advice>
元素来配置事务边界。通过
<tx:method>
元素,我们可以指定需要进行事务管理的方法并定义事务传播行为。
最后,在 Spring 配置文件中,我们需要启用事务管理功能并配置事务通知。
<tx:annotation-driventransaction-manager="transactionManager"/>
我们配置了以上代码,因此Spring 会自动扫描带有 @Transactional 注解的方法,并生成事务通知。
使用注解的事务管理demo
首先第一步也是配置事务管理器和数据源,这一步与声明式事务管理相同,因此不在赘述。
接着定义事务边界,这点与声明式事务管理相比,基于注解的事务管理不再需要在 Spring 配置文件中进行额外的配置。我们只需在服务类中使用 @Transactional 注解即可。
@ServicepublicclassStudentService{// ...@TransactionalpublicvoidaddStudent(Student student){// 添加学生信息,管理系统伪代码省略}@TransactionalpublicvoidupdateStudent(Student student){// 更新学生信息,管理系统伪代码省略}// ...}
通过添加 @Transactional 注解到服务类中的方法上,我们直接就实现了对 addStudent() 和 updateStudent() 方法的事务管理。
同时,我们也可以将 @Transactional 注解应用到接口定义或抽象类的方法上,以便在子类中继承和覆盖时继续享受事务管理功能。
面试这样答
声明式事务管理和基于注解的事务管理是 Spring 提供的两种常用事务管理方式。它们都能够简化事务管理的配置和编写,并提供了灵活的事务特性。
在声明式事务管理中,我们使用 XML 配置或注解来定义事务边界和事务通知。通过使用
<tx:advice>
元素和
<tx:method>
元素,我们可以指定需要进行事务管理的方法并定义事务传播行为。
而基于注解的事务管理更加简洁,只需在服务类的方法上添加 @Transactional 注解即可实现事务管理。
无论是哪种方式,Spring 的事务管理机制都使得我们能够轻松实现数据的一致性和完整性。通过合理配置事务特性,我们可以满足不同业务场景下的事务需求。
文章到这里就先结束了,感兴趣的可以订阅专栏哈,后续会继续分享相关的知识点。
版权归原作者 小威要向诸佬学习呀 所有, 如有侵权,请联系我们删除。