1. spring提供编程式的事务管理与声明式的事务管理:
编程式事务管理:可以清楚的控制事务的边界,可以由我们自行实现事务的开始时间、撤销操作的时机、结束时间,可以实现细粒度的事务控制。
声明式事务管理,大多数情况下不需要细粒度的控制,而采取声明式的事务管理,好处是spring事务管理的相关API可以不用介入程序中,可以自由的插拔(通过配置实现)
Spring的jdbc编程事务管理:
Spring提供了两种方式实现编程式的事务管理,一是直接使用platformTransactionManager的实现,二是使用org.springframework.transaction.support.TransactionTemplate。
前者的使用这里举例是其实现类:DataSourceTransactionManager,之前的spring的jdbc的项目中需要修改下DaoServiceImpl:
package com.springframework.sample.jdbc.dao;
import java.util.ArrayList;
import java.util.List;
import javax.sql.DataSource;
importorg.springframework.dao.DataAccessException;
importorg.springframework.jdbc.core.JdbcTemplate;
importorg.springframework.jdbc.datasource.DataSourceTransactionManager;
importorg.springframework.transaction.TransactionDefinition;
importorg.springframework.transaction.TransactionStatus;
importorg.springframework.transaction.support.DefaultTransactionDefinition;
importcom.springframework.sample.jdbc.pojo.Banzu;
importcom.springframework.sample.jdbc.pojo.BanzuRowMapper;
public class DaoServiceImplimplements DaoInterface {
privateJdbcTemplate jdbcTemplate;
//privateDataSource dataSource;
//加入spring的编程式的事务管理
privateDataSourceTransactionManager transactionManager;
privateDefaultTransactionDefinition def;
publicJdbcTemplate getJdbcTemplate() {
returnjdbcTemplate;
}
publicvoid setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate= jdbcTemplate;
}
publicvoid setDataSource(DataSource dataSource){
this.jdbcTemplate= new JdbcTemplate(dataSource);
transactionManager= new DataSourceTransactionManager(dataSource);
//建立事务定义,明确传输行为为:支持当前事务,如果当前没有则新建
def= new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
}
@Override
publicvoid saveBanzu(Banzu banzu) {
//TODO Auto-generated method stub
Stringsql = "insert into banzu (BANZU_NAME,FUZEREN,BANZUCHENGYUAN) VALUES(?,?,?)";
//获得事务状态描述
TransactionStatusstatus = transactionManager.getTransaction(def);
try{
if(banzu!=null)
{
this.jdbcTemplate.update(sql,new Object[]{banzu.getBanZu(),banzu.getFuZeRen(),banzu.getChengYuan()});
//该处插入有错误会报异常的
jdbcTemplate.update("insetinto banzu (BANZU_NAME,FUZEREN,BANZUCHENGYUAN) VALUES(?,?,?)", newObject[]{"222","333","444"});
}
}catch(DataAccessExceptione){
transactionManager.rollback(status);
throwe;
}
//这里只有不报SQL异常下面的commit才会提交执行的sql语句到库中
transactionManager.commit(status);
}
……
}
这里使用了DataSourceTransactionManager对象,他实现了platformTransactionManager,继承自AbstractPlatformTransactionManager,是针对于特定数据源的事务操作管理类。其中方法:
doBegin(…)
doResume(…)
doSuspend(…)
doCommit(…)
doRollback(…)
等操作方法,而且其中还定义了相应的内部静态类:DataSourceTransactionObject对象可以实例化事务对象
private staticclassDataSourceTransactionObject extends JdbcTransactionObjectSupport {
private boolean newConnectionHolder;
private boolean mustRestoreAutoCommit;
public voidsetConnectionHolder(ConnectionHolder connectionHolder, booleannewConnectionHolder){
super.setConnectionHolder(connectionHolder);
this.newConnectionHolder= newConnectionHolder;
}
public boolean isNewConnectionHolder(){
return this.newConnectionHolder;
}
public voidsetMustRestoreAutoCommit(boolean mustRestoreAutoCommit) {
this.mustRestoreAutoCommit= mustRestoreAutoCommit;
}
public booleanisMustRestoreAutoCommit() {
return this.mustRestoreAutoCommit;
}
public void setRollbackOnly() {
getConnectionHolder().setRollbackOnly();
}
public boolean isRollbackOnly() {
returngetConnectionHolder().isRollbackOnly();
}
}
#DataSourceTransactionManager调用的getTransaction()、rollback()、commit()等都来自于AbstractPlatformTransactionManager类中的实现。
#AbstractTransactionDefinition实现了TransactionDefinition接口,主要设置相关事务的ACID属性,传输性、隔离性、只读、超时限制,具体的可以参考spring的事务1.
此外另一个实现式的编程式事务管理的方法是使用了TransactionTemplate,它简化了编程式事务的分工和异常的处理。其核心的方法是execute,实现了TransactionCallback接口,支持可编程的事务方式。
其构造方法中有一个需要platformTransactionManager参数的
Public TransactionTemplate(PlatformTransactionManagertransctionManager){
This.transactionManager= transactionManager;
}
然后讲下该方法,也是TransactionTemplate的核心方法。
public <T> Texecute(TransactionCallback<T> action) throwsTransactionException {
/*实现CallbackPreferringPlatformTransactionManager接口的可以返回一个transactioncallback的应用,transactioncallback则是对于transaction操作的一个接口。*/
if (this.transactionManagerinstanceofCallbackPreferringPlatformTransactionManager) {
return((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this,action);
}
else {
//通过transactionDefinition获得一个事务,并返回其状态信息
TransactionStatusstatus= this.transactionManager.getTransaction(this);
Tresult;
try {
//事务中处理操作,返回结果
result = action.doInTransaction(status);
}
catch (RuntimeException ex) {
//出现sql异常,回滚
rollbackOnException(status, ex);
throw ex;
}
catch (Error err) {
//编程式事务异常抛出error回滚 threw error ->rollback
rollbackOnException(status, err);
throw err;
}
catch (Exception ex) {
// Transactional code threw unexpected exception ->rollback
rollbackOnException(status, ex);
throw newUndeclaredThrowableException(ex, "TransactionCallback threw undeclaredchecked exception");
}
//不抛出异常的话,将执行的sql内容提交到数据库
this.transactionManager.commit(status);
return result;
}
}
因此可以看到使用TransactionTemplate时,需要借助一个transactionManager,然后执行execute方法,可以直接使用匿名内部类:
transactionManager.execute(newTransacitonCallback(){
publicObject doInTransaction(TransactionStatus status){
return jdbcTemplate.update(“….”);
}
});
如果发生了异常,则会rollback,否则提交事务。如果没有返回值的话也可以使用TransactionCallbackWithoutResult.
public voidsetDataSource(DataSource dataSource){
this.jdbcTemplate = new JdbcTemplate(dataSource);
transactionManager= newDataSourceTransactionManager(dataSource);
//建立事务定义,明确传输行为为:支持当前事务,如果当前没有则新建
//def = new DefaultTransactionDefinition();
//def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
//使用transactionTemplate
this.transactionTemplate= newTransactionTemplate(transactionManager);
}
//在匿名内部类中使用的外部变量,需要声明成final类型,保持一致。
@Override
public void saveBanzu(final Banzu banzu) {
// TODO Auto-generated method stub
final String sql = "insert into banzu(BANZU_NAME,FUZEREN,BANZUCHENGYUAN) VALUES (?,?,?)";
transactionTemplate.execute(newTransactionCallback<Object>(){
public ObjectdoInTransaction(TransactionStatus status){
jdbcTemplate.update(sql, new Object[]{banzu.getBanZu(),banzu.getFuZeRen(),banzu.getChengYuan()});
return null;
}
});
}
使用TransactionTemplate时则是使用其内部的事务处理,只要调用其execute方法,实现TransactionCallback匿名内部类即可。
对于TransactionTemplate的另一个方法
#rollbackOnException()
private voidrollbackOnException(TransactionStatus status, Throwable ex)throwsTransactionException {
logger.debug("Initiating transaction rollback on applicationexception", ex);
try {
this.transactionManager.rollback(status);
}
…可以看到它是private私有的,也就是在其内部调用。也就是在execute方法内部如果出现了异常会调用它。
下面是相应的这部分的类结构关系:
关于声明式事务管理下次继续。