事务相关知识
基本概念知识
-
事务的概念
事务是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作,这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务是一组不可再分割的操作集合。
-
事务的ACID原则
原子性(Atomicity):一个事务已经是一个不可再分割的工作单位。事务中的全部操作要么都做;要么都不做
一致性(Consistency):事务的执行使数据从一个状态转换为另一个状态,但是对于整个数据的完整性保持稳定。
隔离性(Isolation):事务允许多个用户对同一个数据进行并发访问,而不破坏数据的正确性和完整性。同时,并行事务的修改必须与其他并行事务的修改相互独立。
持久性(Durability):一个事务一旦提交,它对数据库中数据的改变会永久存储起来。其他操作不会对它产生影响
spring事务API介绍
PlatformTransactionManager接口是Spring提供的【事务平台管理器】,主要用于管理事务。该接口中提供了三个事务操作的方法
PlatformTransactionManager接口只是代表事务管理的接口,并不知道底层是如何管理事务的,具体如何管理事务则由它的实现类来完成。该接口常见的几个实现类如下
2.TransactionDefinition【事务定义信息】
是一个接口,定义了事务隔离级别、事务传播行为、事务超时时间、事务是否只读
该对象中定义了事务基本属性,并提供了获取事务基本属性的方法
3.TransactionStatus接口是事务的状态,它描述了某一时间点上事务的状态信息。该接口中包含6个方法,具体如下
传播行为(propagation behavior):当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。Spring定义了七种传播行为
隔离级别(isolation level):定义了一个事务可能受其他并发事务的影响程度。多个事务并发运行,经常会操作相同的数据来完成各自的任务,可能会出现脏读,不可重复读和幻读的问题。隔离级别有四种
是否只读(isReadOnly):如果一个方法内都是对数据库的select操作,那么可以设置方法事务为只读,数据库也会对该事务进行特定的优化。只读事务内不能有insert、update、delete的操作
事务超时(timeout):事务可能设计对后端数据库的锁定,所以长时间的事务运行会不必要的占用数据库资源,设置事务超时时间可以及时释放资源
-
事务隔离级别
-
脏读 :在一个事务中读取到了另外一个事务修改的【未提交的数据】,而导致多次读取同一个数据返回的结果不一致 (必须要解决的)
-
不可重复读 : 在一个事务中读取到了另外一个事务修改的【已提交的数据】,而导致多次读取同一个数据返回的结果不一致
-
幻读(虚读): 一个事务读取了几行记录后,另一个事务插入一些记录,幻读就发生了。再后来的查询中,第一个事务就会发现有些原来没有的记录
-
编程式事务管理缺点必须要在业务逻辑中包含额外的事务管理代码。和业务逻辑代码产生了耦合,产生了代码冗余,不方便代码的维护和扩展。
声明式事务管理最大的优点在于开发者无需通过编程的方式来管理事务,只需在配置文件中进行相关的事务规则声明,就可以将事务应用到业务逻辑中。这使得开发人员可以更加专注于核心业务逻辑代码的编写,在一定程度上减少了工作量,提高了开发效率,所以在实际开发中,通常都推荐使用声明式事务管理。
基于XML方式的声明式事务
配置<tx:advice>元素的重点是配置<tx:method>子元素,上图中使用灰色标注的几个属性是<tx:method>元素中的常用属性、
1.添加事务管理器组件
<!--定义事务管理器 -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
2.使用<tx:advice>标签配置事务规则
因为要用到tx标签配置事务,需要修改applicationContext.xml文件头
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd">
使用<tx:advice>标签进一步对事务管理器配置事务规则
<!-- 配置事务规则 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<!-- 定义哪些方法需要进行事务处理,*表示任意字符 -->
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="del*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="moneyTransfer" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
3.使用<aop:config>标签配置事务切面,并应用事务规则
<!-- 定义切面 -->
<aop:config>
<!-- 定义切点范围 -->
<aop:pointcut expression="execution(* service.*.*(..))" id="pointcut"/>
<!-- 应用事务规则 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
</aop:config>
基于注解方式的声明式事务
1.在Spring容器中注册事务注解驱动;
2.在需要事务管理的类或方法上使用@Transactional注解
如果将注解添加在Bean类上,则表示事务的设置对整个Bean类的所有方法都起作用;
如果将注解添加在Bean类中的某个方法上,则表示事务的设置只对该方法有效。
使用@Transactional注解时,可以通过参数配置事务详情:
关键操作:
如果想要代码出错后事务回滚,且代码正常运行正常运行可以这样用try catch
参考:教学笔记、教学书籍