spring事务
事务:事务是访问并可能更新数据库中各中数据项的一个程序执行单元(unit)。
主要是用来保证数据操作的一致性(执行单元),要么全成功,要么全失败。
事务的4个特性:
原子性、一致性、隔离性、持久性。
特性 | 描述 |
---|---|
原子性(Atomicity) | 事务最基本的操作单元,要么全部成功,要么全部失败,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样。 |
一致性(Consistency) | 事务的一致性指的是在一个事务执行之前和执行之后数据库都必须处于一致性状态。如果事务成功地完成,那么系统中所有变化将正确地应用,系统处于有效状态。如果在事务中出现错误,那么系统中的所有变化将自动地回滚,系统返回到原始状态。 |
隔离性(Isolation) | 指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。 |
持久性(Durability) | 指的是只要事务成功结束,它对数据库所做的更新就必须永久保存下来。即使发生系统崩溃,重新启动数据库系统后,数据库还能恢复到事务成功结束时的状态。 |
隔离级别:
- ISOLATION_DEFAULT -1 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。另外四个与JDBC的隔离级别相对应
- ISOLATION_READ_UNCOMMITTED 1 这是事务最低的隔离级别,它充许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻读。
- ISOLATION_READ_COMMITTED 2 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。
- ISOLATION_REPEATABLE_READ 4 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻读。
- ISOLATION_SERIALIZABLE 8 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻读。
传播属性:
PROPAGATION_REQUIRED -- 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS -- 支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY -- 支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW -- 新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED -- 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER -- 以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED -- 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。
前六个策略类似于EJB CMT,第七个(PROPAGATION_NESTED)是Spring所提供的一个特殊变量。
它要求事务管理器或者使用JDBC 3.0 Savepoint API提供嵌套事务行为(如Spring的DataSourceTransactionManager)
事务的原理:
从数据库的角度来看 提供了一种后悔机制(类似于svn/git)。
查询操作是没有事务的,只有增删除才会有默认事务。 执行增删改之前,先将满足条件的数据放入临时表中(数据库在内存中创建一张临时表)。
将数据操作现在临时表中完成,如果没有出现问题,就将数据同步(剪切)到实际的数据表中,并返回影响行数。
如果出现问题,将临时表清空,同时返回错误信息。
spring中事务配置:
1.数据源:实际上就是包含了Connection对象,都要实现DataSource接口。
2.使用spring提供的工具类TransactionManager 事务管理器来管理所有的事务操作(要拿到连接对象)。
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
3.利用切面编程来实现对某一类方法来进行事务统一管理(声明式事务)
<aop:config>
<aop:pointcut expression="execution(public * com.demo..*.service..*Service.*(..))" id="transactionPointcut"/>
<aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice"/>
</aop:config>
4.配置通知规则
<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!—对以add开头的方法进行事务管理-->
<tx:method name="add*" propagation="REQUIRED" rollback-for="Exception,RuntimeException" timeout="-1"/>
<tx:method name="remove*" propagation="REQUIRED" rollback-for="Exception,RuntimeException"/>
<tx:method name="modify*" propagation="REQUIRED" rollback-for="Exception,RuntimeException"/>
<tx:method name="transfer*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="login" propagation="REQUIRED"/>
<tx:method name="query*" read-only="true"/>
</tx:attributes>
</tx:advice>
通过配置通知规则,对代码中以规则开头的方法进行事务管理,并可以配置隔离级别和事务传播。