Spring笔记05-Spring事务
5.1 声明事务管理
ACID 属性:
Atomic原子:All or Nothing
Consistent一致性: DB integrity constraints never violated
Isolated: How transactions see work done by others
Durable: Committed changes are permanent
我们一般是在Service层声明事务。
5.1.1 @Transactional注解
@Transactional
注解允许我们管理一个事务管理器。Spring不直接提供事务管理器,它提供一个hook连接到已经存在的事务管理器,比如我们使用关系数据库,那Spring就是使用关系数据库的事务管理器。Spring的Bean和Entity允许我们请求事务管理器,设置属性(比如超时、只读等)。
应用Spring的事务需要两步:
- 应用
Transactional
注解
a. XML格式
b. 写代码的方式 - 声明Platform Transaction Manager bean
@EnableTransactionManagement
@Transactional
注解可以用于方法或者类。如果应用于一个类,那么这个类中的所有方法都应用了了这个注解,对于应用了类的注解,我们对单独的类重新使用@Transactional
方法来覆盖。
@Transactional
方法提供了一些参数让我们来指定一些配置。
5.1.2 PlatformTransactionManager接口
PlatformTransactionManager
用来代表依赖平台的事务管理器。它的实现类有Hibernate, JPA等事务管理器。
5.1.3 案例:账户应用
首先,我们定义entity:
1 | package lx.spring.core.entities; |
这里我们使用BigDecimal
类型来表示余额。
然后我们创建一个Repository,用来表示数据库的操作:
1 | package lx.spring.core.repositories; |
后面我们将看到如何用Spring Data来处理数据。
第一步,我们用@Transactional
实体。
1 | @Service @Transactional |
第二步是声明Bean来适应事务,我们打开AppConfig
:
1 |
|
注意这里的transactionManagerForTest()
是返回事务管理器的,同时,我们用EnableTransactionManagement
来指明我们的容器用了事务管理。
5.2 Isolation levels 隔离层级
@Transactional
有一个属性是Isolation
的,它是一个枚举,它有一下几个值:
DEFAULT
使用底层数据存储所用的隔离层级READ_COMMITTED
dirty reads are prevented; non-repeatable reads and phantom reads can occur.只有在其他事务提交时在一个事务里才能看到改变后的数据。如果事务需要很久,那就一直锁定直到事务完成。READ_UNCOMMITTED
dirty reads, non-repeatable reads and phantom reads can occur. 两个事务同时对于一行操作。如果一个事务读取了行,然后又修改了数据,那另一个事务可以看到其他事务修改后的数据。这个好处是速度非常快,你没有锁定行,问题是它有一定风险,比如你根据没有提交的数据做了一些动作,但是这些改变又回滚了。所以,使用时需要分析一下。READ_UNCOMMITTED
是最高效但不是最优的选择。REPEATABLE_READ
dirty reads and non-repeatable reads are prevented; phantom reads can occur.如果数据修改后发生了回滚,则回滚前后我们看到的数据都是一样的SERIALIZABLE
dirty reads, non-repeatable reads and phantom reads are prevented 当我们查询或修改时,别的事务不能增加或修改表(整表锁定)
一般情况下我们不会修改这个属性。
5.3 Propagation 传播
Propagation说的是当事务执行时,我们的方法是否也是执行的。我们再回到@Transactional
注解上来,它有一个属性是Propagation
枚举。它有以下值:
MANDATORY
: 1. tx->join tx; 2. no->throw a TransactionRequiredExceptionNESTED
:NEVER
: 1. tx-> throw an exception; 2. no->nothingNOT_SUPPORTED
: 1. tx->suspend tx; run outside tx; resume tx; 2. no->nothingREQUIRED
:最常用,如果一个事务发生,那么我们加入,这是默认的;如果没有,我们创建一个事务。REQUIRES_NEW
:1. tx1-> suspend tx1; create and run tx2; resume tx1; 2. no->create and run txSUPPORTS
: 1. tx->join tx; 2. no->nothing
除了NESTED
,其它的都是来自于J2EE。
5.4 高效事务管理
Spring提供了两种高效高效管理事务的方法:
- 使用
TransactionTemplate
- 使用
PlatfromTransactionManager
实现
5.4.1 TransactionTemplate
TransactionTemplate
非常有用。我们在Service
的构造方法里有提供PlatformTransactionManager
参数:
1 | import org.springframework.transaction.PlatformTransactionManager; |
参数TransactionStatus
有setRollbackOnly()
方法,用于回滚事务。
我们可以在构造方法中设置事务:
1 | public SimpleService(PlatformTransactionManager transactionManager) { |
5.4.2 PlatformTransactionManager
我们也可以使用org.springframework.transaction.PlatformTransactionManager
直接管理会话。将PlatformTransactionManager
直接传给bean,然后可以使用TransactionDefinistion
和TransactionStatus
来初始化会话、回滚、提交等。
在TransactionTemplate
和PlatformTransactionManager
之间有限推荐第一个。