玩转Spring——Spring事务
事务的概念:
多个sql 操作 要么都成功 要么都失败
ACID特性:
原子性(Atomicity)
原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
一致性(Consistency)
事务前后数据的完整性必须保持一致。
隔离性(Isolation)
事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
持久性(Durability)
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
隔离性会导致的问题:
1.脏读:数据已修改事务没提交,另一事务读取到未提交的数据!(事务没提交另一事务就读到未提交的数据)
2不可重复读:同一事务两次读取数据不一样;第一个事务读去数据,第二个事务修改数据提交,第一个事务再一次读取数据,这样第一个事务两次读取的数据将不一致。
3.幻读:两个事务,第一个事务将所有行的数据都修改了,第二个事务将插入一条数据提交,第1个事务提交发现有一条数据并没有修改。
4.丢失更新:当2个事务更新相同的数据源,如果第一个事务被提交,而另外一个事务却被撤销,那么会连同第一个事务所做的跟新也被撤销。也就是说第一个事务做的跟新丢失了。
事务的隔离级别:
Spring 是如何帮我们管理事务(transaction)的?
开发的时候有2种方式:
- Xml
- 注解@transactional
注意:我们这两种方式叫做声明式事务管理,另外还有编程式事务管理,需要把事务管理逻辑写在我们的业务代码中,一般不使用编程式事务管理。
第一种方式:Xml方式开发步骤:
1 导入 jar包 (Spring-tx...)
2 配置(Spring事务管理是通过aop的方式)
2.1 配置连接池
2.2配置事务管理器
2.3采用tx:advice定义一个事务增强
2.4采用aop:config定义切面
如果a方法有事务,b方法也有事务。那如果a调用了b 那到底用谁的?
Spring就提出了一个传播行为(propagation)的概念,用于解决事务方法和非事务方法的相互调用。
常见的传播行为:
第二种方式:注解方式开发步骤:
1.配置事务管理器
<!-- 配置数数据库连接池 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="username" value="root"></property> <property name="password" value="111"></property> <property name="url" value="jdbc:mysql://localhost:3306/test1?characterEncoding=utf-8"></property> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> </bean> <!-- 产生jdbctemplate --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 配置注解的事务处理器 让我们的@Transactional 生效 --> <tx:annotation-driven transaction-manager="transactionManager" />
工作中建议大家使用注解的开发方式,如果整个类上都要用事务,可以直接在类上面使用@Transactional
如果只是某个方法上要使用事务,建议直接在方法上使用@Transactional
可以不用配置传播行为的,使用默认的propagation="REQUIRED" 就好。