5.1.3 Spring注解事务行为

当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如,方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。事务的传播行为可以在@Transactional的属性中指定。Spring定义了7种传播行为,具体如表5-1所示。

表5-1 Spring传播行为

隔离级别定义了一个事务可能受其他并发事务影响的程度。在典型的应用程序中,多个事务并发运行,经常会操作相同的数据来完成各自的任务。并发虽然是必需的,但也可是会导致许多问题,并发事务所导致的问题可以分为以下3类。


• 脏读(Dirty reads):脏读发生在一个事务读取了另一个事务改写但尚未提交的数据。如果改写在稍后被回滚了,那么第一个事务获取的数据就是无效的。

• 不可重复读(Nonrepeatable read):不可重复读发生在一个事务执行相同的查询两次或两次以上,但是每次都得到不同的数据时。这通常是因为另一个并发事务在两次查询期间更新了数据。

• 幻读(Phantom read):幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录。


针对这些问题,Spring提供了5种事务的隔离级别,具体如表5-2所示。

表5-2 Spring隔离级别

@Transactional可以通过propagation属性定义事务行为,属性值分别为REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER以及NESTED,分别对应表5-1中的内容。可以通过isolation属性定义隔离级别,属性值分别为DEFAULT、READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ以及SERIALIZABLE。

还可以通过timeout属性设置事务过期时间,通过readOnly指定当前事务是否是只读事务,通过rollbackFor(noRollbackFor)指定哪个或者哪些异常可以引起(或不可以引起)事务回滚。