Spring 事务
- 数据库事务是企业应用中最为重要的内容之一。
- 事务往往会涉及到注释@Transactional
1. Spring的数据管理器的设计
- 在Spring中数据库事务是通过
PlatformTransactionManager
进行管理的,而能够支持事务的是org.springframework.transaction.support.TransactionTemplate
,它是Spring所提供的事务管理器的模板。
private PlatformTransactionManager transactionManager;
......
@Override
public <T> T execute(TransactionCallback<T> action) throws TransactionException{
if(this.transactionManager instanceof CallbackPreferringPlatformTransactionManager){
return ((CallbackPreferringPlatformTransactionManager)this.transactionManager).execute(this,action);
}else{
TransactionStatus status = this.transactionManager.getTransaction(this);
T result;
try{
result = action.doInTransaction(status);
}catch(RuntimeException ex){
rollbackOnException(status, ex);
throw ex;
}catch(Error ex){
rollbackOnException(status, err);
throw err;
}catch(Throwable ex){
rollbackOnException(status, ex);
throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception");
}
this.transactionManager.commit(status);
return result;
}
}
- 事务的创建、提交和回滚是通过
PlatformTransactionManager
接口来完成。 - 当事务产生异常时会回滚事务,在默认的实现中所有的异常都会回滚,可以通过配置去修改在某些异常发生时回滚或者不会滚事务。
- 当无异常时,会提交事务。
- 多种事务管理器如下
1.1. 数据管理器分类
- 可以看到多个数据库管理器,并且支持JTA事务,常用的是
DataSourceTransactionManager
,集成抽象事务管理器AbstractPlatformTransactionManager
,而AbstractPlatformTransactionManager
又实现了PlatformTransactionManager
。这样Spring就可以如同源码中那样使用PlatformTransactionManager
接口的方法,创建、提交或者回滚事务了。 PlatformTransactionManager
接口的源码如下:
public interface PlatformTransactionManager{
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;
}
2. 通过标签来完成Spring的事务回滚
- 将所有的对于数据库的操作都放置到一个被@Transactional标记的Service方法中可以全部回滚
@Transactional
public boolean UserRegister(ESysUser entity) {
try {
eSysUserDao.insert(entity);
} catch (Exception e) {
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
log.error(e.getMessage(), e);
return false;
}
}
2.1. 根据异常进行回滚
@Transactional(rollbackFor = { Exception.class})
- 没有捕获异常,则会抛出异常,则将doDbStuff1()中的数据库操作进行回滚。
@Transactional(rollbackFor = { Exception.class })
public void test() throws Exception {
doDbStuff1();
doDbStuff2();
}
- 如果在程序中自已捕获异常未往外抛,如下代码事务不会回滚
@Transactional(rollbackFor = { Exception.class })
public void test() {
try {
doDbStuff1();
doDbStuff2();
} catch (Exception e) {
e.printStackTrace();
}
}
- 既要捕获异常,又要回滚
@Transactional(rollbackFor = { Exception.class })
public void test() {
try {
doDbStuff1();
doDbStuff2();
} catch (Exception e) {
e.printStackTrace();
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return;
}
}
2.2. 回滚部分异常
- 使用
Object savePoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
设置回滚点。 - 使用
TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint);
回滚到savePoint。
@Transactional(rollbackFor = Exception.class)
@Override
public void saveEntity() throws Exception{
Object savePoint = null;
try {
userDao.saveUser();
savePoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
studentDao.saveStudent();
int a = 10/0;
}catch (Exception e){
System.out.println("异常了=====" + e);
TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint);
}
}
3. 参考
- 【Java EE】深入Spring数据库事务管理
- spring事务回滚:当同时需要在多个数据表插入数据时,一个出错如何实现全部回滚
- Spring中抛出异常时,既要要返回错误信息,还要做事务回滚
- SpringBoot事务简单操作及手动回滚