什么是事务?

事务是逻辑上的一组操作,要么都执行,要么都不执行。

事务的特点?

  • 原子性(Atomicity): 一个事务(transaction)中的所有操作,或者全部完成,或者全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。即,事务不可分割、不可约简。
  • 一致性(Consistency): 在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设约束、触发器、级联回滚等。
  • 隔离性(Isolation): 数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括未提交读(Read uncommitted)、提交读(read committed)、可重复读(repeatable read)和串行化(Serializable)。
  • 持久性(Durability): 事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

注意:事务是否生效的决定性因素在于数据库引擎是否支持事务。比如,mysql中innodb支持事务,而myisam则不支持事务。

spring事务

spring提供两种事务管理机制:分别为编程式事务声明式事务

编程式事务

编程式事务需要开发者基于底层api如PlatformTransactionManagerTransactionTemplate或者TransactionManager在代码中手动管理事务的开启、提交和回滚等操作。

基于 TransactionTemplate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class SimpleService implements Service {

// single TransactionTemplate shared amongst all methods in this instance
private final TransactionTemplate transactionTemplate;

// use constructor-injection to supply the PlatformTransactionManager
public SimpleService(PlatformTransactionManager transactionManager) {
Assert.notNull(transactionManager, "The 'transactionManager' argument must not be null.");
this.transactionTemplate = new TransactionTemplate(transactionManager);
}

public Object someServiceMethod() {
return transactionTemplate.execute(new TransactionCallback() {

// the code in this method executes in a transactional context
public Object doInTransaction(TransactionStatus status) {
updateOperation1();
return resultOfUpdateOperation2();
}
});
}
}

如果没有返回值,则使用TransactionCallbackWithoutResult

1
2
3
4
5
6
7
transactionTemplate.execute(new TransactionCallbackWithoutResult() {

protected void doInTransactionWithoutResult(TransactionStatus status) {
updateOperation1();
updateOperation2();
}
});

事务执行出错时,将回滚操作放在finally语句块中。

1
2
3
4
5
6
7
8
9
10
11
transactionTemplate.execute(new TransactionCallbackWithoutResult() {

protected void doInTransactionWithoutResult(TransactionStatus status) {
try {
updateOperation1();
updateOperation2();
} catch (SomeBusinessExeption ex) {
status.setRollbackOnly();
}
}
});
基于 PlatfornTransactionManager 的编程式事务

接口中定义了如下三个方法:

1
2
3
4
5
6
7
public interface PlatformTransactionManager {
TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException;

void commit(TransactionStatus var1) throws TransactionException;

void rollback(TransactionStatus var1) throws TransactionException;
}

抽象类AbstractPlatformTransactionManager实现了PlatformTransactionManager接口,针对不同的场景,有不同的实现子类实现。

  • JpaTransactionManager:如果你用jpa来操作db,那么需要用这个管理器来帮你控制事务。
  • DataSourceTransactionManager:如果你用是指定数据源的方式,比如操作数据库用的是:JdbcTemplate、mybatis、ibatis,那么需要用这个管理器来帮你控制事务。
  • HibernateTransactionManager:如果你用hibernate来操作db,那么需要用这个管理器来帮你控制事务。
  • JtaTransactionManager:如果你用的是java中的jta来操作db,这种通常是分布式事务,此时需要用这种管理器来控制事务。
    如下是使用PlatformTransactionManager保障事务的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
// explicitly setting the transaction name is something that can only be done programmatically
def.setName("SomeTxName");
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

TransactionStatus status = txManager.getTransaction(def);
try {
// execute your business logic here
}
catch (MyException ex) {
txManager.rollback(status);
throw ex;
}
txManager.commit(status);

包含这样几个步骤:

  1. 初始化事务
  2. 事务配置
  3. 事务提交
  4. 事务回滚

声明式事务

比较

使用事务时的注意事项

声明式事务的失效场景

引用

1. 11.6 Programmatic transaction management
1. 编程式事务
2. 声明式事务