最近在做报表excel导入插入数据的时候,插入数据之前要清除当前用户和报告期下的数据,删除后执行错误导致删除运行,接口报错,
redis中获取的数据没有刷新,导致再次执行其他操作时报错。
在这里用到DataSourceTransactionManager进行事务管理,可能需要多条sql完成对数据库的操作,比如账户登录,需要匹配用户名和密码,然后要增加积分,还要记录登录的ip和时间,这可能需要三个sql语句,这三个语句应当是一个整体,任意一个sql执行不成功,都表示这个业务没有执行完成,对前面的sql执行进行回滚。
事务是数据库中的概念,就是对数据库的一组操作,由一条或多条sql组成。
事务具有同步的特点,一条sql执行失败,其他sql都不会执行,即要么都执行,要么都不执行
xml配置:
<!-- 定义事务 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/></bean>
<!-- 配置 Annotation 驱动,扫描@Transactional注解的类定义事务 --><tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
<bean id="dataSource" class="net.bull.javamelody.SpringDataSourceFactoryBean"> <property name="targetName" value="kdataDataSource" /></bean>
public class KdataTxUtil {
public static DataSourceTransactionManager getTxManager(){
DataSourceTransactionManager transactionManager = (DataSourceTransactionManager) SpringContextHolder
.getBean("transactionManager");
return transactionManager;
}
public static TransactionStatus newTransaction(){
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 事物隔离级别,开启新事务,这样会比较安全些。
TransactionStatus status = getTxManager().getTransaction(def); // 获得事务状态
return status ;
}
public static void commit(TransactionStatus status) {
if ( status != null) {
getTxManager().commit(status);
}
}
public static void rollback(TransactionStatus status) {
if( status != null) {
getTxManager().rollback(status);
}
}
}
封装controller(web层)调用service接口
public Map callTxService(HttpServletRequest request, HttpServletResponse response,Class<? extends KdataService> serviceClass) {
long start = System.currentTimeMillis() ;
request.setAttribute("_req_start_time",System.currentTimeMillis());
KdataContext.init();
IResult rsParamCheck = new Result();
rsParamCheck.failed("begin param check...");
IResult rs = new Result();
rs.failed("begin process ...");
rs.setRequestTraceId(KdataContext.getContextAsString(KdataContext.SYS_REQUEST_TRACE_ID));
KdataContext.traceHttpServletRequest(request);
Map params = RestParam.parse( request);
KdataContext.traceSetReqParam(params);
TransactionStatus ts = KdataTxUtil.newTransaction() ;//获取事物对象
try {
KdataService kdataService = SpringContextHolder.getBean(serviceClass);
kdataService.doService(params,rs);
KdataTxUtil.commit(ts);
}catch(KdataRollbackException e) {
KdataTxUtil.rollback(ts);
StringBuffer sb = new StringBuffer( e.getMessage());
e.printStackTrace();
rs.setException(Exceptions.getStackTraceAsString(e));
rs.failed( sb.toString());
}catch(Exception e) {
KdataTxUtil.rollback(ts);
StringBuffer sb = new StringBuffer("请求处理异常:"+e.getMessage());
e.printStackTrace();
rs.setException(Exceptions.getStackTraceAsString(e));
if( e instanceof NullPointerException) {
rs.failed("空指针异常:"+Exceptions.getStackTraceAsString(e));
} else {
rs.failed( sb.toString());
}
}
KdataContext.addRequestTraceLog( rs);//添加日志
long end = System.currentTimeMillis(); //System.nanoTime()
rs.setTimeSpent( end-start);
return RestResult.getRestResult(rs);
}