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

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

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

    空間站

    北極心空

      BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
      15 Posts :: 393 Stories :: 160 Comments :: 0 Trackbacks
    ?????????????????????? ?????? 事務(wù)管理最佳實踐多余的話之三
    ????????????? Spring 聲明式事務(wù)管理出錯示例與解決之道
    ?
    ?
    ?
    前言
    今天,發(fā)現(xiàn)了一個以前寫的使用Spring聲明式事務(wù)管理的程序爆出了數(shù)據(jù)庫連接錯誤,感覺是非常典型的一個誤用Spring聲明式事務(wù)管理的例子,拿出來為大家點評一下。
    ?
    ?
    Spring聲明式事務(wù)管理出錯示例
    這個應(yīng)用程序是使用Spring管理的iBatis程序。事務(wù)使用了Spring的聲明式事務(wù)管理。
    爆出了如下的錯誤:
    Caused by:
    java.sql.SQLException : Connection is read-only. Queries leading to data modification are not allowed
    ?
    at com.withub.wcms.manage.collectnews.systemNewsinfo.dao.WcmsSystemNewsinfoDao.add( WcmsSystemNewsinfoDao.java:50 )
    ??? at com.withub.wcms.manage.collectnews.systemNewsinfo.service.WcmsSystemNewsinfoService.saveOrUpdate( WcmsSystemNewsinfoService.java:103 )
    ??? at com.withub.wcms.manage.collectnews.systemNewsinfo.service.WcmsSystemNewsinfoService.formatRawInfoToHtml( WcmsSystemNewsinfoService.java:89 )
    ?
    可以看出,出現(xiàn)的錯誤是,Spring管理下的iBatis使用的數(shù)據(jù)庫連接是只讀的。而在DAO類的方法中,卻使用了修改數(shù)據(jù)庫的iBatis方法。
    ?
    源代碼:

    WcmsSystemNewsinfoDao類的源代碼就不列出來了。這個Dao類的add方法使用了iBatis的update方法,更新數(shù)據(jù)庫數(shù)據(jù)。
    下面是WcmsSystemNewsinfoService類的部分相關(guān)調(diào)用方法的源代碼:
    public?String?formatRawInfoToHtml(String?infoRawId)?throws?Exception{
    ???????WcmsSystemNewsinfoRawModule?wcmsSystemNewsinfoRawModule
    =new?WcmsSystemNewsinfoRawModule();
    ???????wcmsSystemNewsinfoRawModule.setInfoId(infoRawId);
    ???????
    //原表數(shù)據(jù)
    ????????wcmsSystemNewsinfoRawModule=this.getManageNewsinfoService().queryRawInfoById(wcmsSystemNewsinfoRawModule);
    ???????WcmsSystemNewsinfoModule?wcmsSystemNewsinfoModule
    =new?WcmsSystemNewsinfoModule();
    ???????
    //目標表數(shù)據(jù)
    ???????BeanUtils.copyProperties(wcmsSystemNewsinfoModule,?wcmsSystemNewsinfoRawModule);
    ???????
    ???????wcmsSystemNewsinfoModule.setInfoRawId(wcmsSystemNewsinfoRawModule.getInfoId());
    ???????wcmsSystemNewsinfoModule.setInfoId(
    null);
    ???????
    ???????returnthis.saveOrUpdate(wcmsSystemNewsinfoModule);
    ???????
    ????}
    ????
    /**
    ?????*需要把目標表Model信息保存在目標表中。如果該記錄已存在,則更新,否則,新增!
    ?????*
    ?????*@parammodule
    ?????*@throwsException
    ?????
    */
    ????
    public?String?saveOrUpdate(WcmsSystemNewsinfoModule?module)?throws?Exception{
    ???????WcmsSystemNewsinfoModule?loadModule
    =this.getWcmsSystemNewsinfoDao().selectWcmsSystemNewsinfoModuleByInfoRawId(module.getInfoRawId());
    ???????String?infoId
    =null;
    ???????
    if(loadModule==null){
    ???????????
    //插入
    ???????????infoId=this.getWcmsSystemNewsinfoDao().add(module);
    ???????????
    ???????}
    else{
    ???????????
    //更新
    ???????????/**
    ????????????*更新
    ????????????*1,找到主鍵條件
    ????????????
    */
    ???????????infoId
    =loadModule.getInfoId();
    ???????????module.setInfoId(loadModule.getInfoId());
    ???????????
    this.getWcmsSystemNewsinfoDao().updateProcessedInfo(module);
    ???????????
    ???????}
    ???????
    return?infoId;
    ????}
    源代碼說明:
    WcmsSystemNewsinfoService類的formatRawInfoToHtml(String infoRawId)方法,根據(jù)傳入的參數(shù),準備好所需的數(shù)據(jù),然后調(diào)用本類的saveOrUpdate(WcmsSystemNewsinfoModule module)方法。
    saveOrUpdate()方法,根據(jù)情況,調(diào)用WcmsSystemNewsinfoDao類的add或者update方法。
    ?
    Spring事務(wù)配置文件
    一、事務(wù)配置抽象Bean聲明

    <bean?id="txProxyTemplate"?abstract="true"?class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    ???????
    <property?name="transactionManager"?ref="transactionManager"/>
    ???????
    <property?name="transactionAttributes">
    ???????????
    <props>
    ??????????????
    <prop?key="*">readOnly</prop>
    ??????????????
    <prop?key="add*">PROPAGATION_REQUIRED,-Exception</prop>
    ??????????????
    <prop?key="save*">PROPAGATION_REQUIRED,-Exception</prop>
    ??????????????
    <prop?key="modify*">PROPAGATION_REQUIRED,-Exception</prop>
    ??????????????
    <prop?key="update*">PROPAGATION_REQUIRED,-Exception</prop>
    ??????????????
    <prop?key="delete*">PROPAGATION_REQUIRED,-Exception</prop>
    ??????????????
    <prop?key="remove*">PROPAGATION_REQUIRED,-Exception</prop>
    ??????????????
    <prop?key="query*">PROPAGATION_REQUIRED,?readOnly,-Exception</prop>
    ??????????????
    <prop?key="load*">PROPAGATION_REQUIRED,?-Exception</prop>
    ???????????
    </props>
    ???????
    </property>
    ????
    </bean>


    二、服務(wù)類的Spring聲明式事務(wù)管理

    <!--?
    ????wcmsSystemNewsinfoService
    ?????
    -->
    ????
    <bean?id="wcmsSystemNewsinfoService"
    ???????parent
    ="txProxyTemplate">
    ???????
    <property?name="target">
    ???????????
    <ref?bean="wcmsSystemNewsinfoServiceTarget"/>
    ???????
    </property>
    ????
    ????
    </bean>


    錯誤解析
    錯誤的原因就在上面的Spring聲明式事務(wù)里。執(zhí)行WcmsSystemNewsinfoService類的formatRawInfoToHtml()方法時,會應(yīng)用txProxyTemplate的配置,由于它的方法名與所有的特殊配置都不匹配,因此,會應(yīng)用第一個聲明式事務(wù):
    ??? <prop key="*">readOnly</prop>
    因此,SpringAOP創(chuàng)建了一個只讀的數(shù)據(jù)庫連接和事務(wù)。
    然后,調(diào)用WcmsSystemNewsinfoService類的saveOrUpdate()方法,也會查找上面的事務(wù)配置,匹配:
    <prop key="save*">PROPAGATION_REQUIRED,-Exception</prop>
    SpringAOP會去得到數(shù)據(jù)庫連接和設(shè)置事務(wù)。由于在本地線程變量中已經(jīng)找到了前面提供的只讀連接,就會直接使用這個數(shù)據(jù)庫連接,并在其上設(shè)置事務(wù)。
    最后,調(diào)用WcmsSystemNewsinfoDao類的add方法。由于使用的是只讀連接,執(zhí)行add方法中的update語句,就發(fā)生了上面的錯誤:
    Caused by:
    java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed
    ?
    ?
    Spring真的能夠管理一切嗎?
    像上面這樣的Spring事務(wù)配置和Service、Dao的寫法,應(yīng)當(dāng)說是相當(dāng)普遍的,我們認為Spring已經(jīng)把數(shù)據(jù)庫連接、事務(wù)、O-R映射等等管得妥妥當(dāng)當(dāng)了,不用我們再操心了,再理解事務(wù)了!
    真的如此嗎?錯!
    漠視數(shù)據(jù)庫、漠視事務(wù),我們的系統(tǒng)到底有多少類似的隱患?我們的業(yè)務(wù)服務(wù)類Service浪費了多少SPringAOP的幫助?降低了多少性能?
    Spring、EJB這樣的聲明式事務(wù),確實大大方便了我們處理數(shù)據(jù)庫連接和事務(wù)。但是,我們還是需要自己理解業(yè)務(wù)邏輯對數(shù)據(jù)庫連接,對事務(wù)的需要!
    工具只能幫助我們解決我們認識到的問題,解決不了我們都沒理解的問題。
    ?
    ??? 不能再把一切扔給框架、容器、工具!首先理解你的業(yè)務(wù)邏輯,理解你要實現(xiàn)的功能,然后搞清楚框架、容器、工具會幫助我們做什么。只有理解了自己的業(yè)務(wù)邏輯,理解了自己的代碼,理解了自己要用到的第三方代碼,才能真正完美地實現(xiàn)我們需要的功能!
    ?
    用我們的命名方法來重構(gòu)上面的問題代碼
    一、給Service類中的2個方法加上后綴名標識對事務(wù)的依賴
    ??? 當(dāng)然,Service接口相應(yīng)的方法也要改變。

    /*?(non-Javadoc)
    ?????*?@see?com.withub.wcms.manage.collectnews.systemNewsinfo.service.IWcmsSystemNewsinfoService#formatRawInfoToHtml(java.lang.String)
    ?????
    */
    ????
    public?String?formatRawInfoToHtmlTransaction(String?infoRawId)?throws?Exception{
    ???????WcmsSystemNewsinfoRawModule?wcmsSystemNewsinfoRawModule
    =new?WcmsSystemNewsinfoRawModule();
    ???????wcmsSystemNewsinfoRawModule.setInfoId(infoRawId);
    ???????
    //原表數(shù)據(jù)
    ????????wcmsSystemNewsinfoRawModule=this.getManageNewsinfoService().queryRawInfoById(wcmsSystemNewsinfoRawModule);
    ????
    ???????WcmsSystemNewsinfoModule?wcmsSystemNewsinfoModule
    =new?WcmsSystemNewsinfoModule();
    ???????
    //目標表數(shù)據(jù)
    ???????BeanUtils.copyProperties(wcmsSystemNewsinfoModule,?wcmsSystemNewsinfoRawModule);
    ???????
    ???????wcmsSystemNewsinfoModule.setInfoRawId(wcmsSystemNewsinfoRawModule.getInfoId());
    ???????wcmsSystemNewsinfoModule.setInfoId(
    null);
    ???????
    ???????returnthis.saveOrUpdateDao(wcmsSystemNewsinfoModule);
    ???????
    ????}
    ????
    /**
    ?????*需要把目標表Model信息保存在目標表中。如果該記錄已存在,則更新,否則,新增!
    ?????*
    ?????*@parammodule
    ?????*@throwsException
    ?????
    */
    ????
    public?String?saveOrUpdateDao(WcmsSystemNewsinfoModule?module)?throws?Exception{
    ???????WcmsSystemNewsinfoModule?loadModule
    =this.getWcmsSystemNewsinfoDao().selectWcmsSystemNewsinfoModuleByInfoRawId(module.getInfoRawId());
    ???????String?infoId
    =null;
    ???????
    if(loadModule==null){
    ???????????
    //插入
    ???????????infoId=this.getWcmsSystemNewsinfoDao().add(module);
    ???????????
    ???????}
    else{
    ???????????
    //更新
    ???????????/**
    ????????????*更新
    ????????????*1,找到主鍵條件
    ????????
    */
    ???????????infoId
    =loadModule.getInfoId();
    ???????????module.setInfoId(loadModule.getInfoId());
    ???????????
    this.getWcmsSystemNewsinfoDao().updateProcessedInfo(module);
    ???????????
    ???????}
    ???????
    return?infoId;
    ????}
    這樣,formatRawInfoToHtmlTransaction方法可以直接被最終用戶調(diào)用。它將能夠創(chuàng)建或得到數(shù)據(jù)庫連接,管理事務(wù),最后關(guān)閉數(shù)據(jù)庫連接。
    而,saveOrUpdateDao方法,不能直接被最終用戶調(diào)用。如果它需要數(shù)據(jù)庫連接,它可以使用本地線程變量中保存的數(shù)據(jù)庫連接。
    ?
    二、修改Service類的聲明式事務(wù)的配置文件

    <!--?
    ????wcmsSystemNewsinfoService
    ?????
    -->
    ????
    <bean?id="wcmsSystemNewsinfoService"
    ???????parent
    ="txProxyTemplate">
    ???????
    <property?name="target">
    ???????????
    <ref?bean="wcmsSystemNewsinfoServiceTarget"/>
    ???????
    </property>
    ???????
    <property?name="transactionAttributes">
    ???????????
    <props>
    ??????????????
    <prop?key="*Transaction">PROPAGATION_REQUIRED,-Exception</prop>
    ???????????
    </props>
    ???????
    </property>
    ????
    ????
    </bean>


    這里,重載了txProxyTemplate的聲明式事務(wù)配置。我們只對Service類中的以Transaction結(jié)尾的方法,應(yīng)用事務(wù),在發(fā)生異常時,回滾。
    這樣,Transaction方法直接或者間接調(diào)用的DAO接口中的方法,就可以使用本地線程變量中保存的由Transaction方法的AOP代理方法創(chuàng)建的數(shù)據(jù)庫連接。
    數(shù)據(jù)庫連接和事務(wù)被真正的擺平了!世界真美好!
    ?
    ?
    ?
    ?
    ?

    Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1423460

    posted on 2006-12-02 23:33 蘆葦 閱讀(874) 評論(0)  編輯  收藏 所屬分類: Spring
    主站蜘蛛池模板: 亚洲四虎永久在线播放| 亚洲精品无码av中文字幕| 久久久国产精品亚洲一区| 久9久9精品免费观看| 亚洲人成无码网站久久99热国产| 手机永久免费的AV在线电影网| 国产嫩草影院精品免费网址| 亚洲人成7777影视在线观看| 免费观看理论片毛片| 中文字幕乱理片免费完整的| 亚洲美女视频一区二区三区| 国产jizzjizz视频免费看| 国产成人AV片无码免费| 亚洲中文字幕AV每天更新| 亚洲中文字幕无码一久久区| 国产做国产爱免费视频| 在线精品亚洲一区二区三区| 丁香花免费完整高清观看 | 亚洲XX00视频| 日本免费人成视频在线观看| 亚洲视频精品在线| 免费国产成人午夜电影| 99久久久国产精品免费蜜臀| 美女被艹免费视频| 亚洲制服丝袜第一页| 亚洲精品无码乱码成人| 国产精品无码一区二区三区免费| 久久这里只精品99re免费| 久久精品熟女亚洲av麻豆| www.亚洲色图.com| 美女网站免费福利视频| a毛看片免费观看视频| 久久综合亚洲色hezyo| 俄罗斯极品美女毛片免费播放| 亚洲免费福利视频| 国产自国产自愉自愉免费24区| 国产午夜亚洲精品不卡| 亚洲人成综合在线播放| 亚洲国产老鸭窝一区二区三区 | 中国亚洲女人69内射少妇| 日本人护士免费xxxx视频|