<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    hk2000c技術專欄

    技術源于哲學,哲學來源于生活 關心生活,關注健康,關心他人

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      111 隨筆 :: 1 文章 :: 28 評論 :: 0 Trackbacks

    spring自建事務管理模塊。而且這個事務管理是一個抽象設計,可以應用到很多場合,包括普通的DataSource,jta,jms和hibernate上。 

    要正確使用spring的事務,首先需要了解spring在事務設計上的一些概念 
    統觀spring事務,圍繞著兩個核心PlatformTransactionManager和TransactionStatus

    PlatformTransactionManager 直譯過來就是平臺相關事務,這里的平臺指的是“事務源”,包括剛才我說的DataSource,jta等等。這些無一不是一個事務源。廣義的說,凡是可以完成事務性操作的對象,都可以設計出相對應的PlatformTransactionManager,只要這個事務源支持commit,rollback 和getTransaction語意。

    查看spring代碼,可以發現這些manager實現事務,就是調用事務源的事務操作方法

    比如

    HibernateTransactionManager
    java代碼:

    protected void doCommit(DefaultTransactionStatus status) {
    HibernateTransactionObject txObject = (HibernateTransactionObject) status.getTransaction();
    if (status.isDebug()) {
    logger.debug("Committing Hibernate transaction on session [" +
    txObject.getSessionHolder().getSession() + "]";
    }
    try {
    txObject.getSessionHolder().getTransaction().commit();
    }
    ...

    }

     

    jdbc 的DataSourceTransactionManager
    java代碼:

    protected void doCommit(DefaultTransactionStatus status) {
    DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
    Connection con = txObject.getConnectionHolder().getConnection();
    if (status.isDebug()) {
    logger.debug("Committing JDBC transaction on connection [" + con + "]";
    }
    try {
    con.commit();
    }
    ...
    }

     

    那么PlatformTransactionManager以什么依據處理事務呢?
    是TransactionStatus
    查看api發現這個接口有三個方法
    isNewTransaction() ,isRollbackOnly(),setRollbackOnly()
    PlatformTransactionManager 就是根據前兩個方法決定是否要創建一個新事務,是要遞交還是回滾。至于第三個方法是改變事務當前狀態的,很多地方都要用到,偏偏 PlatformTransactionManager自身好像不怎么用,畢竟事務狀態的改變是由程序員代碼決定的,不需要一個manager多管閑事。

    總結上面所說的,spring的事務由PlatformTransactionManager管理,manager最后調用事務源的方法來實現一個事務過程。而manager通過TransactionStatus 來決定如何實現。

    接下去說spring事務中的TransactionTemplate和TransactionInterceptor

    TransactionTemplate 其實和spring中其他的template的作用類似,起到化簡代碼的作用,不要被它那么長的名字嚇倒了,事實上這個template并不是什么非常核心的對象。如果比較學究派的,可以去看看template設計模式,在此就不再對此贅述了。
    為什么要有TransactionTemplate?先來看看如果沒有TransactionTemplate,我們的代碼該怎么寫

    先來看看spring reference中的一段代碼
    java代碼:

    DefaultTransactionDefinition def = new DefaultTransactionDefinition()
    def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

    TransactionStatus status = transactionManager.getTransaction(def);

    try {
    // execute your business logic here
    } catch (MyException ex) {
    transactionManager.rollback(status);
    throw ex;
    }
    transactionManager.commit(status);

    這是直接使用transactionManager的例子,可以看到真正執行business logic 的地方是在try當中那段,前后的代碼都是為了完成事務管理的。如果每個business logic都要寫上那么一段,我肯定是瘋了。我們翻出TransactionTemplate的代碼看看他怎么化簡了我們的代碼

    java代碼:

    public Object execute(TransactionCallback action) throws TransactionException {
    TransactionStatus status = this.transactionManager.getTransaction(this);
    Object result = null;
    try {
    result = action.doInTransaction(status);
    }
    catch (RuntimeException ex) {
    // transactional code threw application exception -> rollback
    rollbackOnException(status, ex);
    throw ex;
    }
    catch (Error err) {
    // transactional code threw error -> rollback
    rollbackOnException(status, err);
    throw err;
    }
    this.transactionManager.commit(status);
    return result;
    }


    同上面的代碼如出一轍,前后是事務處理代碼,當中那段result = action.doInTransaction(status);是我們的應用代碼。至于action是什么,全看各位的需要了。但是有一點要主要,如果利用TransactionTemplate,那么他不管你扔出什么異常都會回滾事務,但是回滾的是哪個事務呢?繼續挖代碼
    java代碼:

    private void rollbackOnException(TransactionStatus status, Throwable ex) throws TransactionException {
    if (logger.isDebugEnabled()) {
    logger.debug("Initiating transaction rollback on application exception", ex);
    }
    try {
    this.transactionManager.rollback(status);
    }
    catch (RuntimeException ex2) {
    logger.error("Application exception overridden by rollback exception", ex);
    throw ex2;
    }
    catch (Error err) {
    logger.error("Application exception overridden by rollback error", ex);
    throw err;
    }
    }

    真相大白,是對template所持有的某個transactionManager進行回滾。所以如果你的應用代碼用的是事務源a的一些資源,比如到服務器 a的一個datasource,但是你的transactionManager管理的是另一些資源,比如服務器b的一個datasource,代碼鐵定不會正常運行

    特別是在一些多事務源的程序里,這點千萬不能搞錯。如果多個事務源之間要完成全局事務,還是老老實實用分布式事務管理服務吧(jta)

    那么TransactionInterceptor是干什么的?這個是spring 的聲明式事務的支持方式。因為用 TransactionTemplate要硬編碼,而且調整事務策略很麻煩(不是說不能調。舉個例子原來程序拋出異常A需要回滾,現在不需要要,我就可以把a catch吃掉。這時候template就不會回滾了。但是每次調整都要重寫編碼。)而用TransactionInterceptor就可以將這些調整寫在配置中。我們再來挖TransactionInterceptor的代碼

    java代碼:

    public Object invoke(MethodInvocation invocation) throws Throwable {
    // Work out the target class: may be null.
    // The TransactionAttributeSource should be passed the target class
    // as well as the method, which may be from an interface
    Class targetClass = (invocation.getThis() != null) ? invocation.getThis().getClass() : null;

    // Create transaction if necessary
    TransactionInfo txInfo = createTransactionIfNecessary(invocation.getMethod(), targetClass);

    Object retVal = null;
    try {
    // This is an around advice.
    // Invoke the next interceptor in the chain.
    // This will normally result in a target object being invoked.
    retVal = invocation.proceed();
    }
    catch (Throwable ex) {
    // target invocation exception
    doCloseTransactionAfterThrowing(txInfo, ex);
    throw ex;
    }
    finally {
    doFinally(txInfo);
    }
    doCommitTransactionAfterReturning(txInfo);

    return retVal;
    }

    萬變不離其宗。

    所以使用spring的事務管理需要作這些事
    1,設置好事務源,比如DataSource,hibernate的session。如果有多個事務源要考慮他們之間是否有全局事務,如果有,老老實實用jta,否則就需要自己寫一個manager了
    2,設置manager,根據你的事務源選擇對應的PlatformTransactionManager
    3,選擇實現事物的方式,用template還是interceptor。用template代碼直觀點,但是template所管轄的manager和你應用代碼所用的事務源要一致。如果用interceptor千萬注意,一定要調用interceptor那個bean,而不是原始的那個target。在壇子上我已經看到至少有兩個朋友說spring事物不起作用,從配置和代碼上看都正確,這時要好好查查,調用的bean是哪一個。
    4,這個是設計問題了,推薦事務處于一個較高層次,比如service上的某個函數,而底層的dao可以不考慮事務,否則可能會出現事務嵌套,增加程序復雜度。

    posted on 2007-11-01 01:36 hk2000c 閱讀(302) 評論(0)  編輯  收藏 所屬分類: CMS項目開發
    主站蜘蛛池模板: 日韩精品无码一区二区三区免费| 国产亚洲玖玖玖在线观看| 国产自偷亚洲精品页65页| 亚洲国产精品碰碰| 亚洲精品乱码久久久久久蜜桃图片| 亚洲毛片基地日韩毛片基地| 亚洲网站在线观看| 67194熟妇在线永久免费观看 | 一本色道久久综合亚洲精品| 亚洲?V无码乱码国产精品| 日韩亚洲国产二区| 亚洲欧洲久久av| 免费毛片在线看片免费丝瓜视频 | 日本一区二区在线免费观看| 久久精品国产亚洲av高清漫画| 亚洲AV成人片色在线观看| 少妇中文字幕乱码亚洲影视| 亚洲AV无码久久寂寞少妇| 国产公开免费人成视频| 国产成人免费永久播放视频平台| 日本免费一二区在线电影| 免费中文字幕在线观看| 亚洲综合色区在线观看| 亚洲精品夜夜夜妓女网| 国产免费卡一卡三卡乱码| 亚洲av日韩片在线观看| 国内精品99亚洲免费高清| 久久精品国产精品亚洲艾| 77777_亚洲午夜久久多人| 国产精品亚洲专区在线观看| 亚洲国产欧洲综合997久久| 男女污污污超污视频免费在线看| aaa毛片免费观看| 美女黄频a美女大全免费皮| 高清免费久久午夜精品| 青青操在线免费观看| 1000部啪啪毛片免费看| 大学生美女毛片免费视频| 亚洲AV成人潮喷综合网| 亚洲成在人天堂在线| 成人亚洲国产va天堂|