1、回顾事务
● 一组业务,要么都成功要么都失败,把一组事务当成一个业务来做
● 事务在项目开发过程非常重要,涉及到数据的一致性的问题,不容马虎!
● 事务管理是企业级应用程序开发中必备技术,用来确保数据的完整性和一致性。
● 事务四个属性ACID
a. 原子性(atomicity)
■ 事务是原子性操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要么完全不起作用
b. 一致性(consistency)
■ 一旦所有事务动作完成,事务就要被提交。数据和资源处于一种满足业务规则的一致性状态中
c. 隔离性(isolation)
■ 可能多个事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏
d. 持久性(durability)
■ 事务一旦完成,无论系统发生什么错误,结果都不会受到影响。通常情况下,事务的结果被写到持久化存储器中
2、spring中的事务管理
● 声明式事务
●
<!--结合aop实现事务的织入-->
<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--给哪些方法配置事务-->
<!--配置事务的传播特性 propagation="REQUIRED" 默认为REQUIRED -->
<tx:attributes>
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="delete" propagation="REQUIRED"/>
<tx:method name="update" propagation="REQUIRED"/>
<tx:method name="search*" propagation="REQUIRED"/>
<tx:method name="get" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
配置事务切入
<!--配置事务切入-->
<aop:config>
<aop:pointcut id="txPointcut" expression="execution(* cn.zhy.dao.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>
完整的配置文件
<?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:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--xmlns:context="http://www.springframework.org/schema/context" 注意别导错了-->
<!--开启组件扫描功能 扫描cn.zhy.pojo包下所有类是否添加了@Component注解-->
<!-- <context:component-scan base-package="cn.zhy"/>-->
<!-- <context:annotation-config/>-->
<!-- <!–开启Aop注解支持–>-->
<aop:aspectj-autoproxy/>
<!--DataSource 使用Spring的数据源替换Mybatis配置
我们这里使用的是Spring提供的JDBC org.springframework.jdbc.datasource
-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url"
value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2b8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!--配置sqlSessionFactory-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">
<property name="dataSource" ref="dataSource"/>
<!--绑定mabatis配置文件-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="mapperLocations" value="classpath:cn/zhy/mapper/*.xml"/>
</bean>
<!--SqlSessionTemplate就是我们使用的sqlSession-->
<bean class="org.mybatis.spring.SqlSessionTemplate" id="sqlSession">
<!--SqlSessionTemplate中没有set方法,只能通过构造器注入-->
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
<!--配置声明式事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--结合aop实现事务的织入-->
<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--给哪些方法配置事务-->
<!--配置事务的传播特性 propagation="REQUIRED" 默认为REQUIRED -->
<tx:attributes>
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="delete" propagation="REQUIRED"/>
<tx:method name="update" propagation="REQUIRED"/>
<tx:method name="search*" propagation="REQUIRED"/>
<tx:method name="get" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--配置事务切入-->
<aop:config>
<aop:pointcut id="txPointcut" expression="execution(* cn.zhy.dao.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>
</beans>
为什么需要配置事务?
● 如果不配置,就需要我们手动提交控制事务;
● 事务在项目开发过程非常重要,涉及到数据的一致性的问题,不容马虎!
事务隔离级别
事务回滚注解
@Transactional(rollbackFor = Exception.class) 加载service层实现类的方法上
2.4 事务的隔离级别
在我们学习数据库的时候,涉及到事务这一模块的时候经常会涉及到的三个名词就是
● 脏读
● 不可重复读
● 幻读
脏读 :
脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问 这个数据,然后使用了这个数据。
不可重复读
是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两 次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不 可重复读。例如,一个编辑人员两次读取同一文档,但在两次读取之间,作者重写了该文档。当编辑人员第二次读取文档时,文档已更改。原始读取不可重复。如果 只有在作者全部完成编写后编辑人员才可以读取文档,则可以避免该问题。
幻读
是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。 同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象 发生了幻觉一样。例如,一个编辑人员更改作者提交的文档,但当生产部门将其更改内容合并到该文档的主复本时,发现作者已将未编辑的新材料添加到该文档中。 如果在编辑人员和生产部门完成对原始文档的处理之前,任何人都不能将新材料添加到文档中,则可以避免该问题。
设置事务的隔离级别来解决这个问题