文章目录
- 1.事务
- 1.1事务的概念
- 1.2jdbc事务的操作
- 1.3事务的四大特性(ACID)
- 1.4并发访问问题----由隔离性引起
- 1.5MySQL数据库共定义了四种隔离级别
- 2编程式事务控制相关对象
- 2.1PlatformTransactionManager
- 2.2TransactionDefinition
- 2.3TransactionStatus
- 3.声明式事务控制
- 3.1什么是声明式事务控制
- 3.2声明式事务控制的实现
- 3.2.1基于xml相关配置
- 3.2.2基于注解的配置
- 3.2.2.1注解配置声明式事务控制解析
- 3.2.2.2声明式事务控制的配置要点
1.事务
1.1事务的概念
事务指逻辑上的一组操作,组成这组操作的各个单元,要不全部成功,要不全部不成功。
1.2jdbc事务的操作
默认是自动事务:
执行sql语句:executeUpdate() ---- 每执行一次executeUpdate方法 代表 事务自动提交
通过jdbc的API手动事务:
开启事务:conn.setAutoComnmit(false);
提交事务:conn.commit();
回滚事务:conn.rollback();
注意:控制事务的connnection必须是同一个
1.3事务的四大特性(ACID)
1.3.1、原子性(Atomicity)
原子性是指事务是一个不可分割的工作单位,事务中的操作要么全部成功,要么全部失败。比如在同一个事务中的SQL语句,要么全部执行成功,要么全部执行失败
1.3.2、一致性(Consistency)
官网上事务一致性的概念是:事务必须使数据库从一个一致性状态变换到另外一个一致性状态。以转账为例子,A向B转账,假设转账之前这两个用户的钱加起来总共是2000,那么A向B转账之后,不管这两个账户怎么转,A用户的钱和B用户的钱加起来的总额还是2000,这个就是事务的一致性。
1.3.3、隔离性(Isolation)
事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
1.3.4、持久性(Durability)
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响
1.4并发访问问题----由隔离性引起
1)脏读:B事务读取到了A事务尚未提交的数据
这是非常危险的,假设A向B转帐100元,对应sql语句如下所示
1.update account set money=money+100 where name=‘B’;
2.update account set money=money-100 where name=‘A’;
当第1条sql执行完,第2条还没执行(A未提交时),如果此时B查询自己的帐户,就会发现自己多了100元钱。如果A等B走后再回滚,B就会损失100元。
2)不可重复读:一个事务中 两次读取的数据的内容不一致
例如:例如银行想查询A帐户余额,第一次查询A帐户为200元,此时A向帐户内存了100元并提交了,银行接着又进行了一次查询,此时A帐户为300元了。银行两次查询不一致,可能就会很困惑,不知道哪次查询是准的。
3)幻读/虚读: 虚读(幻读)是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。
如丙存款100元未提交,这时银行做报表统计account表中所有用户的总额为500元,然后丙提交了,这时银行再统计发现帐户为600元了,造成虚读同样会使银行不知所措,到底以哪个为准。
1.5MySQL数据库共定义了四种隔离级别
Serializable(串行化):可避免脏读、不可重复读、虚读情况的发生。
Repeatable read(可重复读):可避免脏读、不可重复读情况的发生。
Read committed(读已提交):可避免脏读情况发生。
Read uncommitted(读未提交):最低级别,以上情况均无法保证。
相关内容见:
2编程式事务控制相关对象
2.1PlatformTransactionManager
PlatformTransactionManager接口是spring的事务管理器,它里面提供了常用的操作事务的方法
方法 | 说明 |
TransactionStatus getTransaction(TransactionDefination) | 获取事务的状态信息 |
void commit(TransactionStatus status) | 提交事务 |
void rollback(TransactionStatus status) | 回滚事务 |
注意:
PlatformTransactionManager 是接口类型,不同的Dao层技术则有不同的实现类
2.2TransactionDefinition
TransactionDefinition是事务的定义信息对象,里面有如下方法:
方法 | 说明 |
int getIsolationLevel() | 获得事务的隔离级别 |
int getPropogationBehavior() | 获得事务的传播行为 |
int getTimeout() | 获得超时时间 |
Boolean isReadonly() | 是否只读 |
- ISOLATION_DEFAULT
- ISOLATION_READ_UNCOMMITTED (脏读)
- ISOLATION_READ_COMMITTED(不可重复读)
- ISOLATION_REPEATABLE_READ(幻读)
- ISOLATION_SERIALIZABLE(串行化:可避免脏读、不可重复读、幻读 )
2.事务传播行为 - REQUIRED:A调B,如果A当前没有事务,B就新建一个事务,如果A已经存在一个事务,B加入A的事务。一般的选择(默认)
- SUOPORTYS:支持当前事务,如果当前没有事务,就以非事务的方式执行
- MANDATORY:使用当前事务,如果没事务就抛出异常
- REQUERS_NEW:新建事务,如果在当前事务中,把当前事务挂起
- NOT_SUPPORTED:以非事务的方式执行操作,如果当前;存在事务,就把当前事务挂起
- NEVER:以非事务方式运行,如果当前存在事务,抛出异常
- NESTED:如果当前存在事务则在嵌套事务内执行,如果当前没有事务,则执行REQUIRED类似的操作
- 超时时间:默认值是-1,没有时间限制。如果有,以秒为单位进行设置
- 是否只读:建议查询是设为只读
2.3TransactionStatus
TransactionStatus接口提供的是事务具体的运行状态,方法介绍如下
方法 | 说明 |
boolean hasSavepoint() | 是否存储回滚点 |
boolean isCompleted() | 事务是否完成 |
boolean isNewTransaction() | 是否是新事务 |
boolean isRollbackOnly() | 事务是否回滚 |
3.声明式事务控制
3.1什么是声明式事务控制
Spring的声明式事务控制顾名思义就是采用声明的方式来处理事务。这里所说的声明,就是指在配置文件中声明,用在Spring配置文件中声明式的处理事务来代替代码式的处理事务
声明式事务处理的作用
- 事务管理不侵入开发的组件。具体来说,业务逻辑对象就不会意识到正在事务管理之中,事实上也应该如此,因为业务管理属于系统层面的服务,而不是业务逻辑的一部分,如果想改变事务管理策划的话,也只需要在定义文件中重新配置即可
- 在不需要事务管理的时候,只有在设定文件修改y一下,即可移去事务管理业务,无需改变代码重新编译,这样维护起来及其方便
注意:Spring声明式事务控制底层就是AOP
3.2声明式事务控制的实现
声明式事务控制明确事项
- 谁是切点?
- 谁是通知?
- 谁是切面?
声明式事务控制的配置要点
- 平台事务管理器的配置
- 事务通知的配置
- 事务aop织入的配置
3.2.1基于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 http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:property-placeholder location="jdbc.properties"></context:property-placeholder>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${driver}"></property>
<property name="jdbcUrl" value="${url}"></property>
<property name="user" value="${name}"></property>
<property name="password" value="${password}"></property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="accountDao" class="com.blb.DaoImpl.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<!-- 目标对象 内部方法就是切点 -->
<bean id="userServer" class="com.blb.ServerImpl.UserServerImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>
<!-- 配置平台事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--通知 事务增强 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--设置事务的属性信息 -->
<tx:attributes>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<!-- 配置事务织入-->
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.blb.ServerImpl.UserServerImpl.exchange())"></aop:advisor>
</aop:config>
</beans>
其中,< tx:method >切点方法是事务参数的配置,例如
<tx:attributes>
<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" timeout="-1" read-only="false"/>
</tx:attributes>
</tx:advice>
name:切点名称
isolation:事务的隔离级别
propogation:事务的传播行为
timeout:超时时间
read-only:是否只读
3.2.2基于注解的配置
3.2.2.1注解配置声明式事务控制解析
- 使用@Transactional在需要进行事务控制的类或方法上修饰,注解可用的属性同xml配置方式,例如:隔离级别,传播行为等
- 直接使用在类上,那么该类下的所有方法都使用同一套注解配置项参数
- 使用在方法上,那么该类可以采用不同是=的事务参数配置
- xml配置文件中要开启事务的注解驱动
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
3.2.2.2声明式事务控制的配置要点
- 平台事务管理器配置(xml方式)
- 事务通知的配置(@transactional注解配置)
- 事务注解驱动的配置< tx:annotation-driven/ >