操作数据时,免不了使用事务。
其中事务有几个特点
① 原子性
事务的原子性是指事务必须是一个原子的操作序列单元。事务中包含的各项操作在一次执行过程中,只允许出现两种状态之一,要么都成功,要么都失败
任何一项操作都会导致整个事务的失败,同时其它已经被执行的操作都将被撤销并回滚,只有所有的操作全部成功,整个事务才算是成功完成
② 一致性(Consistency)
事务的一致性是指事务的执行不能破坏数据库数据的完整性和一致性,一个事务在执行之前和执行之后,数据库都必须处以一致性状态。
比如:如果从A账户转账到B账户,不可能因为A账户扣了钱,而B账户没有加钱
③ 隔离性
事务的隔离性是指在并发环境中,并发的事务是互相隔离的,一个事务的执行不能被其它事务干扰。也就是说,不同的事务并发操作相同的数据时,每个事务都有各自完整的数据空间。
一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务是不能互相干扰的
④ 持久性(Duration)
事务的持久性是指事务一旦提交后,数据库中的数据必须被永久的保存下来。即使服务器系统崩溃或服务器宕机等故障。只要数据库重新启动,那么一定能够将其恢复到事务成功结束后的状态
使用事务借助注解@Transactional
举个例子
@Transactional(transactionManager = "xxxTransactionManager", propagation = Propagation.NOT_SUPPORTED,rollbackFor = Exception.class)
其中transactionManager为事务管理器名称,propagation是事务传播行为,rollbackFor是事务什么时候回滚
事务传播行为:
1. REQUIRED 支持当前事务;如果不存在,就创建一个新的。 如果是事务方法嵌套调用,标有required的方法会将外事务直接拿过来使用,如果此事内部出现异常回滚会使外事务方法也回滚!! 即受外层调用者影响,也会影响外层的事务。
2. SUPPORTS支持当前事务;如果不存在,则执行非事务。此行为本身并不会创建事务。当一个方法上标识为supports时,外部方法开启了事务并调用此方法,那么该方法也是一个事务的方法。
如果外部方法没有开启事务,则该方法就是一个不带事务的方法。
3. NOT_SUPPORTED执行非事务处理,如果存在的话,暂停当前事务。明确指定被标识的方法不要用事务。外部事务方法调用此方法时,事务不会进到此方法(即把外部事务挂起),直到此方法执行完后。
4. NEVER不支持当前的事务;如果当前事务存在,则抛出异常。
5. MANDATORY支持当前事务;如果不存在当前事务,则抛出异常。这与never是一对反义词。
6. NESTED如果当前事务存在,在嵌套事务中执行,内部事务方法异常回滚并不会影响外部方法。
7. REQUIRES_NEW无论如何都创建一个新的事务来执行被标识的方法。一般局部数据操作一致性都用此方法,外面的事务对其不影响,不管外层是否提交回滚,它里面的内容会根据自己的执行情况,该提交就提交,该回滚就回滚。但是它会对外层的事务有影响,如果它里面执行时出现异常不仅自己的内容回滚,也会导致外层事务也回滚。不受外层调用者影响,但会影响外层的事务。
要根据实际的场景使用不用的事务传播行为。
另外需要注意的时,truncate table和create table时事务是自动提交的。
有时候为了减少事务影响的范围,我们会写一个个小的方法单独来操作数据,当事务夹在这些小的方法上时,在springBoot中,直接调用事务是不会生效的。
要用这种方式调用:
((XxxServiceImpl) AopContext.currentProxy()).do();