DataSourceTransactionManager進行事務管理


  最近在做報表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);
}

 




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM