一:Spring事务简介
什么是事务:
数据库事务是指作为单个逻辑工作单元执行的一系列操作,这些操作要么一起成功,要么一起失败,是一个不可分割的工作单元。
在我们日常工作中,涉及到事务的场景非常多,一个service 中往往需要调用不同的 dao 层方法,这些方法要么同时成功要么同时失败,我们需要在service层确保这一点。
说到事务最典型的案例就是转账了:
张三要给李四转账 500块钱,这里涉及到两个操作,从张三的账户上减去500块钱,给李四的账户添加500块钱,这两个操作要么同时成功要么同时失败,如何确保他们同时成功或者同时失败呢?答案就是事务
事务有四大特性(ACID):
- 原子性(Atomicity):一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。即,事务不可分割、不可约简。
- 一致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设约束、触发器、级联回滚等。
- 隔离性(Isolation):数据库允许多个并发事务同时对其数据进行读写和修改,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括未提交读(Read Uncommitted)、提交读(Read Committed)、可重复读(Repeatable Read)和串行化(Serializable)
- 持久性(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。这就是事务的四大特性。
以上就是事务的四大特性。
二:Spring中的事务
2.1:两种用法
Spring 作为Java 开发中的基础设施,对于事务也提供了很好的支持,总体上来说, Spring 支持两种类型的事务,声明式事务和编程式事务。
编程式事务类似于 Jdbc事务的写法,需要将事务的代码嵌入到业务逻辑中,这样代码的耦合度较高,而声明式事务通过AOP 的思想能够有效的将事务和业务逻辑代码解耦,因此在实际开发中,声明式事务得到了广泛的应用,而编程式事务则较少使用,考虑到文章内容的完整,本文对两种事务方式都会介绍。
2.2 :三大基础设施
Spring 中对事务的支持提供了三大基础设施,我们先来了解下。
- PlatformTransactionManager/TransactionManager
- TransactionDefinition
- TransactionStatus
这三个核心类是 Spring 处理事务的核心类。
2.2.1
1.PlatformTransactionManager/TransactionManager 是事务处理的核心类,它有很多实现类
PlatformTransactionManager定义如下:
public interface PlatformTransactionManager extends TransactionManager {
TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException;
void commit(TransactionStatus var1) throws TransactionException;
void rollback(TransactionStatus var1) throws TransactionException;
}
可以看到 PlatformTransactionManager中定义了基本的事务操作方法,这些事务操作方法都是平台无关的,具体的实现都是由不同的子类来实现的。
这就像 JDBC 一样,SUN公司制定标准,其他数据库厂商提供具体的实现。这么做的好处就是我们 Java程序员只需要掌握好这套标准即可,不用去管接口的具体实现。以 PlatformTransactionManager为例,它有众多实现,如果你使用的是 JDBC 那么可以将DataSourceTransactionManager作为事务管理器;如果你使用的是Hibernate,那么可以将HibernateTransactionManager 作为事务管理器;如果你使用的是JPA,那么可以将JpaTransactionManager 作为事务管理器。DataSourceTransactionManager、HibernateTransact ionManager 以及JpaTransactionManager 都是PlatformTransactio nManager 的具体实现,但是我们并不需要掌握这些具体实现类的用法,我们只需要掌握好PlatformTransactionManager的用法即可。 PlatformTransactionManager中主要有如下三个方法:
1.1.getTransaction()
getTransaction()是根据传入的TransactionDefinition获取一个事务对象,
TransactionDefinition 中定义了一些事务的基本规则,例如传播性、隔离级别等。
1.2.commit()
commit()方法用来提交事务。
1.3.rollback()用于回滚事务。
2.TransactionDefinition
public interface TransactionDefinition {
int PROPAGATION_REQUIRED = 0;
int PROPAGATION_SUPPORTS = 1;
int PROPAGATION_MANDATORY = 2;
int PROPAGATION_REQUIRES_NEW = 3;
int PROPAGATION_NOT_SUPPORTED = 4;
int PROPAGATION_NEVER = 5;
int PROPAGATION_NESTED = 6;
int ISOLATION_DEFAULT = -1;
int ISOLATION_READ_UNCOMMITTED = 1;
int ISOLATION_READ_COMMITTED = 2;
int ISOLATION_REPEATABLE_READ = 4;
int ISOLATION_SERIALIZABLE = 8;
int TIMEOUT_DEFAULT = -1;
default int getPropagationBehavior() {
return 0;
}
default int getIsolationLevel() {
return -1;
}
default int getTimeout() {
return -1;
}
default boolean isReadOnly() {
return false;
}
@Nullable
default String getName() {
return null;
}
static TransactionDefinition withDefaults() {
return StaticTransactionDefinition.INSTANCE;
}
}
TransactionDefinition用于描述事务的具体规则,也称为事务的属性:
- 隔离性
- 传播性
- 回滚规则
- 超时时间
- 是否只读
TransactionDefinition类中方法:
- getlsolationLevel(),获取事务的隔离级别
- getName(),获取事务的名称
- getPropagationBehavior(),获取事务的传播性
- getTimeout(),获取事务的超时时间
- isReadOnly(),获取事务是否是只读事务
TransactionDefinition也有诸多的实现类:
如果使用了编程式事务的话,直接使用DefaultTransactionDefinition即可。
3.TransactionStatus 方法和 extends的方法里面也有很多方法
TransactionStatus:
public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable {
boolean hasSavepoint();
void flush();
}
TransactionExecution:
public interface TransactionExecution {
boolean isNewTransaction();
void setRollbackOnly();
boolean isRollbackOnly();
boolean isCompleted();
}
SavepointManager:
public interface SavepointManager {
Object createSavepoint() throws TransactionException;
void rollbackToSavepoint(Object var1) throws TransactionException;
void releaseSavepoint(Object var1) throws TransactionException;
}
所以说TransactionStatus有这么多方法
以上就是Spring事务的三个基础。
编程式事务举个例子:
public class shiwu {
@Autowired
private DataSourceTransactionManager transactionManager;
public void excute(){
DefaultTransactionDefinition transactionDefinition= new DefaultTransactionDefinition();
//事务名称
transactionDefinition.setName("richfit");
//四大隔离级别中的一个,默认是这个
transactionDefinition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
//传播特性
transactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);
Savepoint savepoint1 = null;
Savepoint savepoint2 = null;
try {
try {
//创建事务回滚点
savepoint1 = (Savepoint)transactionStatus.createSavepoint();
//业务逻辑1处理
}catch (Exception e1){
//回滚
transactionStatus.rollbackToSavepoint(savepoint1);
}
try {
//创建事务回滚点
savepoint2 = (Savepoint)transactionStatus.createSavepoint();
//业务逻辑2处理
}catch (Exception e2){
//回滚
transactionStatus.rollbackToSavepoint(savepoint2);
}
//业务1和业务2处理完commit提交事务
transactionManager.commit(transactionStatus);
}catch (Exception ex){
}finally {
//防止有遗漏的回滚
if (!transactionStatus.isCompleted()){
transactionManager.rollback(transactionStatus);
}
}
}
}