一、什么是实务?
事务就是一系列的动作,它们被当作一个单独的工作单元。这些动作要么全部完成,要么全部不起作用。
二、实务的关键特性
① 原子性(atomicity):事务室一个原子操作,有一系列动作组成。事务的原子性确保动作要么全部完成,要么完全不起作用
② 一致性(consistency):一旦所有事务动作完成,事务就被提交。数据和资源就处于一种满足业务规则的一致性状态中
③ 隔离性(isolation):可能有许多事务会同时处理相同的数据,因此每个事物都应该与其他事务隔离开来,防止数据损坏
④ 持久性(durability):一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响。通常情况下,事务的结果被写到持久化存储器中
三、数据隔离级别
隔离级别 | 脏读 | 不可重复读 | 幻象读 | 第一类丢失更新 | 第二类丢失更新 |
READ UNCOMMITED | 允许 | 允许 | 允许 | 不允许 | 允许 |
READ COMMITED(默认) | 不允许 | 允许 | 允许 | 不允许 | 允许 |
REPEATABLE READ | 不允许 | 不允许 | 允许 | 不允许 | 不允许 |
SERIALIZABLE | 不允许 | 不允许 | 不允许 | 不允许 | 不允许 |
四、实务的传播属性
事务的传播行为可以由传播属性指定。Spring定义了7种传播行为:
PROPAGATION_REQUIRED | 如果当前没有事务,就新建一个事务,如果已经存在一个事务,加入到这个事务中。这是最常见的选择。 |
PROPAGATION_SUPPORTS | 支持当前事务,如果当前没有事务,就以非事务方式执行。 |
PROPAGATION_MANDATORY | 使用当前的事务,如果当前没有事务,就抛出异常。 |
PROPAGATION_REQUIRES_NEW | 新建事务,如果当前存在事务,把当前事务挂起。 |
PROPAGATION_NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 |
PROPAGATION_NEVER | 以非事务方式执行,如果当前存在事务,则抛出异常。 |
PROPAGATION_NESTED | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。 |
五、并发事务所导致的问题
在同一个应用程序或者不同应用程序中的多个事务在同一个数据集上并发执行时,可能会出现许多意外的问题。
并发事务所导致的问题可以分为以下三类:
① 脏读:脏读发生在一个事务读取了另一个事务改写但尚未提交的数据时。如果改写在稍后被回滚了,那么第一个事务获取的数据就是无效的。
② 不可重复读:不可重复读发生在一个事务执行相同的查询两次或两次以上,但是每次都得到不同的数据时。这通常是因为另一个并发事务在两次查询期间更新了数据
③ 幻读:幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录
六、声明式实务
1、xml配置管理实务
事务管理是一种横切关注点
<tx: advice id="">这个元素是用来声明事务的
<tx:advice id="advice">
<tx:attributes>
<tx:method name="*" isolation="READ_COMMITTED"/>
<tx:method name="get*" read-only="true" />
</tx:attributes>
</tx:advice>
声明事务之后,把事务和切入点关联起来,所以必须在 <aop:config> 元素中声明一个增强器通知与切入点关联起来
<aop:config>
<aop:pointcut expression="execution (* cn.bdqn.story.service.*.*(..))" id="point"/>
<aop:advisor advice-ref="advice" pointcut-ref="point"/>
</aop:config>
由于 SpringAOP 是基于代理的方法, 所以只能增强公共方法.因此,只有公有方法才能通过 Spring AOP 进行事务管理
七、用@Transactional注解声明事务管理
不会啊