Dev Zone
          偏執狂才能生存,人生/事業的路上需要再堅持一下
          但是又怎么說得清堅持的結果,道得盡堅持的含義

          我使用的是GEF0.10(http://gef.tigris.org),在某一個Fig上點擊鼠標右鍵彈出PopupMenu時,發現有閃爍的現象,經過追查發現,一個鼠標右擊動作會分別觸發Editor.mousePressed(e)、mouseReleased(e)、mouseClicked(e)三個事件,這些事件最終都要流經ModeManager,而ModeManager采取的是廣播的方式分發這些事件,把這些事件依次轉發給mode對列中的所有Mode。ModePopup是默認的一個Mode之一,負責提供Fig的彈出菜單功能。而ModePopup中的這三個事件都作了如下的判斷: 

             public void mouseClicked(MouseEvent me) {
                  boolean popUpDisplayed 
          = false;
                  
          if(me.isPopupTrigger() || me.getModifiers() == InputEvent.BUTTON3_MASK) {
                      popUpDisplayed 
          = showPopup(me);
                      
          if (LOG.isDebugEnabled()) {
                          
          if (popUpDisplayed) LOG.debug("MousePressed detected as a popup and popup displayed and event consumed");
                          
          else  LOG.debug("MousePressed detected as a popup but no popup to display");
                      }
                      
          return;
               }
                  LOG.debug(
          "MousePressed is not a popup trigger");
              }

           

          其中加紅的這段不知道為什么要作me.getModifiers() == InputEvent.BUTTON3_MASK的判斷,加上這個判斷后只要是鼠標右擊動作,ModePopup的mousePressed、mouseReleased和mouseClicked事件中showPopup的代碼都要被執行,這樣在一個鼠標右擊動作中實際上彈出了三次PopupMenu,因此造成了閃爍。解決辦法是extend默認的ModePopup,覆蓋這三個方法,將判斷改成if ( me.isPopupTrigger())即可。

          posted @ 2005-05-17 22:10 dev 閱讀(633) | 評論 (0)編輯 收藏
           

          今天做了一個測試,發現Hibernate的dynamic-update只在兩種條件下生效:

          1。同一session內,對已經persisit的對象進行update,這里的“已經persist”是指update之前先進行了create或者load調用。代碼示例:

          Session session = openSession();
          User user 
          = (User)session.load(User.class,new Long(12));
          user.setAddress(
          null);
          session.update(user);
          session.flush();

          將hibernate配置成show_sql=true,可以看到update產生的sql語句。

          2。不同session之間,update傳入的對象是另一個session中的persist對象(對該對象調用了create或者load方法)。代碼示例:

          Session session1 = openSession();
          User user 
          = (User)session1.load(User.class,new Long(12));

          Session session2 
          = openSession();
          user.setAddress(
          null);
          session2.merge(user);
          session2.flush();


          如果將session2.merge(..)改成update,則會更新所有可更新的屬性。

          posted @ 2005-05-17 22:10 dev 閱讀(2220) | 評論 (0)編輯 收藏
           

          今天在csdn上看到了一篇介紹PDCA理論在項目管理中應用的blog,很是感慨,想想才到公司的時候老總也給我們做過相關培訓,一年下來,要是沒有看到這篇blog,鐵定是想不起來了。PDCA(計劃、實施、檢察、優化)是一個很好的理論,現摘錄這篇blog的內容如下,以為珍藏。

          以下內容出自:http://blog.csdn.net/wwwxuhong/archive/2004/12/20/222804.aspx 

          項目管理是個很大的課題
          所有的事物都有其規律

          項目管理的規律是什么?
          前幾天看到一個理論讓我眼睛一亮,陳述如下,希望對大家有點啟發

          PDCA循環是由美國統計學家戴明博士提出來的,它反映了質量管理活動的規律。P(Plan)表示計劃;D(Do)表示執行;C(Check)表示檢查;A(Action)表示處理。PDCA循環是提高產品質量,改善企業經營管理的重要方法,是質量保證體系運轉的基本方式。

          項目管理的PDCA環。
          PDCA是指以下四個階段,這四個階段是環環相扣的,這個周期是周而復始的
          P  Plan  計劃
          D  Do    實施
          C Check 檢查
          A Action 總結、再優化

          不管是多大的項目,還是多小的任務,如果都用PDCA環實施,環環相扣,就可以大大提高管理的質量,最大程度地保障項目的成功實施。

          PDCA分以下八上步驟
          計劃階段
              1、分析現狀
              2、找出問題的原因
              3、分析產生問題的原因
              4、找出其中的主要原因
              5、擬訂措施計劃
          實施階段
              6、執行技術組織措施計劃
          檢查階段
              7、把執行結果與預定目標對比
          總結、再優化階段
              8、鞏固成績,進行標準化

          轉貼一篇相關文章
            在企業中,通過眾多小小的變革可能實現對整個企業的持久改善,從而獲得巨大的成效。這在日語中叫做“改善”(kaizen),每一步都很小,這兒一個小變化,那兒一個小改進,但幾年后就能發展出完全不同的產品、工序或服務。
            PDCA循環是由美國統計學家戴明博士提出來的,它反映了質量管理活動的規律。P(Plan)表示計劃;D(Do)表示執行;C(Check)表示檢查;A(Action)表示處理。PDCA循環是提高產品質量,改善企業經營管理的重要方法,是質量保證體系運轉的基本方式。

            PDCA循環的特點PDCA表明了質量管理活動的四個階段,每個階段又分為若干步驟。

            在計劃階段,要通過市場調查、用戶訪問等,摸清用戶對產品質量的要求,確定質量政策、質量目標和質量計劃等。它包括現狀調查、原因分析、確定要因和制定計劃四個步驟。

            在執行階段,要實施上一階段所規定的內容,如根據質量標準進行產品設計、試制、試驗,其中包括計劃執行前的人員培訓。它只有一個步驟:執行計劃。

            在檢查階段,主要是在計劃執行過程之中或執行之后,檢查執行情況,看是否符合計劃的預期結果。該階段也只有一個步驟:效果檢查。

            在處理階段,主要是根據檢查結果,采取相應的措施。鞏固成績,把成功的經驗盡可能納入標準,進行標準化,遺留問題則轉入下一個PDCA循環去解決。它包括兩個步驟:鞏固措施和下一步的打算。

            PDCA循環四階段各步驟。

            1.PDCA循環一定要按順序進行,它靠組織的力量來推動,像車輪一樣向前滾進,周而復始,不斷循環。

            2.企業每個科室、車間、工段、班組,直至個人的工作,均有一個PDCA循環,這樣一層一層地解決問題,而且大環套小環,一環扣一環,小環保大環,推動大循環。

            這里,大環與小環的關系,主要是通過質量計劃指標連接起來,上一級的管理循環是下一級管理循環的根據,下一級的管理循環又是上一級管理循環的組成部分和具體保證。通過各個小循環的不斷轉動,推動上一級循環,以至整個企業循環不停轉動。通過各方面的循環,把企業各項工作有機地組織起來,納入企業質量保證體系,實現總的預定質量目標。因此,PDCA循環的轉動,不是哪一個人的力量,而是組織的力量、集體的力量,是整個企業全體職工推動的結果。

            3.每通過一次PDCA循環,都要進行總結,提出新目標,再進行第二次PDCA循環,使質量管理的車輪滾滾向前。PDCA每循環一次,質量水平和管理水平均提高一步。

            PDCA循環不僅是質量管理活動規律的科學總結,是開展質量管理活動的科學程序,也是一種科學管理的工作方法。它同樣可以在質量管理活動以外發揮重要效用。

            PDCA管理法在營銷中的運用在運用PDCA循環進行市場營銷管理方面,已經有一些優秀企業走在了前頭。

            海爾集團純熟地采用PDCA管理法來實施銷售任務的計劃、組織和控制。每年年終,集團商流、各產品本部根據本年度的銷售額完成情況,結合各產品的發展趨勢及競爭對手分析等信息,制定下一年度的銷售計劃,然后將這一計劃分解至全國11個銷售事業部。銷售事業部長根據各工貿上年的完成情況、市場狀況分析等信息再將銷售額計劃分解至其下屬各工貿公司。工貿公司總經理將任務分解至各區域經理,由他們將任務下達至區域代表,區域代表將自己的銷售額任務分解至其所管轄的營銷網絡。同時,海爾還從時間緯度上進行分解:年度計劃分解至月度,月度計劃分解至每日。這樣,處于管理層的每位管理者都可以對下屬每日的工作狀況進行監督,并及時實施糾偏,最終控制每一個具體網點。海爾集團在新產品開發、新品上市等所有方面都遵循PDCA管理方法。這種做法可以保證“人人都管事,事事有人管”,避免出現管理的真空。

            PDCA管理法運用于每日的事務管理,就形成了獨具海爾特色的OEC日清體系。每人均處于相應的崗位上,每一崗位均有不同的職責,并分配相應的指標,員工的激勵直接與指標掛鉤。指標又可分為主項指標與輔項指標以及臨時任務指標等。每人在當日晚上分析一天的各項任務完成情況,并找出差距原因及糾偏辦法,以使今后的工作質量得到提高,由此構成了持續不斷的改進過程。員工在做完當日總結后,對明日工作做出計劃,然后將OEC日清表交至主管領導處,由主管領導進行審核控制并對下屬的當日工作進行評價和激勵。

            OEC管理法的主要理念,海爾認為是“堅持兩個原則,最大限度地對待兩種人”,即堅持閉環原則,堅持優化原則,最大限度地關心員工的生活,最大限度地滿足用戶的需求。所謂閉環原則,指凡事要善始善終,都必須遵循PDCA循環,而且是螺旋上升。所謂優化原則,指根據木桶理論,找出薄弱項,及時整改,提高全系統的水平。在一個企業的運營過程中,必然存在著許多環節,只要找出制約企業經濟效益提高的某一關鍵環節,把首要矛盾解決了,其他矛盾就可以迎刃而解。

            張瑞敏說,海爾生產線每天要出大大小小幾萬臺家電產品,我們不能考慮出了問題如何處理,而要追求不出任何問題。OEC管理法把質量互變規律作為基本思想,堅持日事日清,積沙成塔,使員工素養、企業素質與管理水平的提高寓于每日工作之中,通過日積月累的管理進步,使生產力諸要素的組合與運行達到合理優化的狀態,不增加投入就可使現實生產力獲得盡可能大的提高,從而令管理收到事半功倍的效果。

            海爾把PDCA運用到企業內部的營銷隊伍管理上,那么,這種管理方法對外部營銷是否適用呢?

            上海通用汽車公司成功地把此方法應用于自己的經銷體系中,極大地改善了經銷商的服務。在其近100家經銷商中,上海通用奉行的政策是,對一些業務表現不好、不能完成上海通用的要求、不能在市場上進行有效的開拓,或者在售后服務方面不能夠完全按照上海通用的理念和規范去操作的經銷商,會先給他們做一個PDCA改進計劃。完成了這個計劃性的四部曲后,經銷商的整個市場營銷的管理工作應該會隨之步入一個良性循環的軌道。如果還是不行,經銷商就會被淘汰掉。

            由上可知,PDCA管理法的核心在于通過持續不斷的改進,使企業的各項事務在有效控制的狀態下向預定目標發展。

          posted @ 2005-05-17 22:09 dev 閱讀(1842) | 評論 (0)編輯 收藏
           

            先前的項目采用的是TyrexFactory作為事務工廠的實現,但是運行的過程中發現很不穩定,處理大對象時容易出現事務超時的錯誤,即使事務設置的超時時間很長也是這樣,將jotm及其相關jar copy 到lib中之后,換成JotmFactory,發現TransactionFactory.getTransactionFactory竟然報NoSuchElementException。后來發現是carol.jar中的CarolConfiguration需要裝載jndi.properties文件進行初始化,而tyrex.jar自身有一個同名的文件,正是因為CoralConfiguration裝載了這個同名的文件才產生了異常,去掉tyrex.jar就可以了。

          posted @ 2005-05-17 22:08 dev 閱讀(449) | 評論 (0)編輯 收藏
           
          Ofbiz2.1有兩個bug,都涉及到線程安全性,小并發的時候不容易發現,大并發下有時候會出現,并發數越高出現的頻度就比較高,尤其對于實體引擎的那個bug,在系統初始化的時候如果遭遇大并發,會有一定頻度的出現。
           
          1。entity engine的ModelEntity.getField方法存在線程安全隱患,會造成 XXXX is not a field of XXX的異常,以下是原有代碼片斷:

              
          public ModelField getField(String fieldName) {
                  
          if (fieldName == nullreturn null;
                  if (fieldsMap == null) {
                      fieldsMap = new HashMap(fields.size());
                      for (int i = 0; i < fields.size(); i++) {
                          ModelField field = (ModelField) fields.get(i);
                          fieldsMap.put(field.name, field);
                  }
                  return (ModelField) fieldsMap.get(fieldName);
              }

          由于getField方法沒有同步(會造成性能下降),因此紅色標標注的那段代碼存在線程安全問題,必須進行同步。在大并發下如果多個調用這個方法,最先調用的線程沒有執行完循環的情況下,后續的線程通過最后的語句return的時候得到的就是Null(fieldsMap已經被第一個線程賦值了,后續線程不會進入紅色標準的代碼區域)。
          修改后的代碼如下:
             public ModelField getField(String fieldName) {
                  
          if (fieldName == nullreturn null;
                  
          if (fieldsMap == null) {
                       createFields();
                  }
                  
          return (ModelField) fieldsMap.get(fieldName);
              }

              
          public synchronized void createFields()
              {
                       fieldsMap 
          = new HashMap(fields.size());
           
                       
          for (int i = 0; i < fields.size(); i++) {
                           ModelField field 
          = (ModelField) fields.get(i);
           
                           fieldsMap.put(field.name, field);
                       }
              }
           
          這個Bug在3.0中已經被修正。
           
          2。UtilCache.get方法同樣存在線程安全隱患,會造成LinkedList.remove或者LinedList.addFirst的空值針異常,不注意還會以為是LinkedList的bug。以下是原代碼片斷:
              public Object get(Object key) {
                  
          if (key == null) {
                      missCount
          ++;
                      
          return null;
                  }
                  UtilCache.CacheLine line 
          = (UtilCache.CacheLine) cacheLineTable.get(key);
                  
          if (hasExpired(line)) {
                      
          // note that print.info in debug.properties cannot be checked through UtilProperties here, it would cause infinite recursion
                      
          // if (Debug.infoOn()) Debug.logInfo("Element has expired with key " + key);
                      remove(key);
                      line 
          = null;
                  }
                  
          if (line == null) {
                      
          // if (Debug.infoOn()) Debug.logInfo("Element not found with key " + key);
                      missCount++;
                      
          return null;
                  }
                  
          // if (Debug.infoOn()) Debug.logInfo("Element found with key " + key);
                  hitCount++;
                  if (maxSize > 0) {
                      keyLRUList.remove(key);
                      keyLRUList.addFirst(key);
                  }

                  return line.getValue();
              }
          紅色標準的部分是有問題的代碼,修改后的代碼如下:
              public Object get(Object key) {
                  
          if (key == null) {
                      missCount
          ++;
                      
          return null;
                  }
                  UtilCache.CacheLine line 
          = (UtilCache.CacheLine) cacheLineTable.get(key);
                  
          if (hasExpired(line)) {
                      
          // note that print.info in debug.properties cannot be checked through UtilProperties here, it would cause infinite recursion
                      
          // if (Debug.infoOn()) Debug.logInfo("Element has expired with key " + key);
                      remove(key);
                      line 
          = null;
                  }
                  
          if (line == null) {
                      
          // if (Debug.infoOn()) Debug.logInfo("Element not found with key " + key);
                      missCount++;
                      
          return null;
                  }
                  
          // if (Debug.infoOn()) Debug.logInfo("Element found with key " + key);
                  hitCount++;
                  
          if (maxSize > 0) {
                      synchronized ( 
          this)
                      {
                           keyLRUList.remove(key);
                           keyLRUList.addFirst(key);
                      }
                  }
                  
          return line.getValue();
              }

          這個BUG在3.0種也修正了。
          posted @ 2005-05-17 22:07 dev 閱讀(319) | 評論 (0)編輯 收藏
           
          1。XAPool是如何wrap jdbc driver返回的PreparedStatement的。
          以下是StandardConnectionHandler中的checkPreparedCache代碼片斷
          ????synchronized?PreparedStatement?checkPreparedCache(
          ????????String?sql,
          ????????
          int?type,
          ????????
          int?concurrency)
          ????????throws?SQLException?{
          ????????log.debug(
          ????????????
          "StandardConnectionHandle:checkPreparedCache?sql='"?+?sql?+?"'");
          ????????PreparedStatement?ret?
          =?null;?//?the?return?value
          ????????
          //?NOTE?-?We?include?the?Connection?in?the?lookup?key.?This?has?no
          ????????
          //?effect?here?but?is?needed?by?StandardXAConnection?where?the?the?physical
          ????????
          //?Connection?used?can?vary?over?time?depending?on?the?global?transaction.
          ????????String?lookupKey?=?sql?+?type?+?concurrency;
          ????????
          //?used?to?lookup?statements
          ????????if?(preparedStatementCache?!=?null)?{
          ????????????Object?obj?
          =?preparedStatementCache.get(lookupKey);
          ????????????
          //?see?if?there's?a?PreparedStatement?already
          ????????????if?(obj?!=?null)?{?//?if?there?is
          ????????????????ret?=?(PreparedStatement)?obj;?//?use?as?return?value
          ????????????????try?{
          ????????????????????ret.clearParameters();?
          //?make?it?look?like?new
          ????????????????}?catch?(SQLException?e)?{
          ????????????????????
          //?Bad?statement,?so?we?have?to?create?a?new?one
          ????????????????????ret?=?createPreparedStatement(sql,?type,?concurrency);
          ????????????????}

          ????????????????preparedStatementCache.remove(lookupKey);
          ????????????????
          //?make?sure?it?cannot?be?re-used
          ????????????????inUse.put(lookupKey,?ret);
          ????????????????
          //?make?sure?it?gets?reused?by?later?delegates
          ????????????}?else?{?//?no?PreparedStatement?ready
          ????????????????ret?=?createPreparedStatement(sql,?type,?concurrency);
          ????????????????inUse.put(lookupKey,?ret);
          ????????????????
          //?will?get?saved?in?prepared?statement?cache
          ????????????}
          ????????}?
          else?{
          ????????????ret?
          =?createPreparedStatement(sql,?type,?concurrency);
          ????????}
          ????????
          //?We?don't?actually?give?the?application?a?real?PreparedStatement.?Instead
          ????????
          //?they?get?a?StandardPreparedStatement?that?delegates?everything?except
          ????????
          //?PreparedStatement.close();

          ????????ret?
          =?new?StandardPreparedStatement(this,?ret,?lookupKey);
          ????????
          return?ret;
          ????}

          2。StandardPreparedStatement的Close方法代碼片斷
          ????public?void?close()?throws?SQLException?{
          ????????
          //?Note?no?check?for?already?closed?-?some?servers?make?mistakes
          ????????closed?=?true;
          ????????
          if?(con.preparedStmtCacheSize?==?0)?{
          ????????????
          //?no?cache,?so?we?just?close
          ????????????if?(ps?!=?null)?{
          ????????????????ps.close();
          ????????????}
          ????????}?
          else?{
          ????????????con.returnToCache(key);
          ????????????
          //?return?the?underlying?statement?to?the?cache
          ????????}
          ????}

          3。xapool StandardPoolDataSource的getConnection 原理:
          ???? StandardPoolDataSource.getConnection --> GenericPool.checkOut-->StandardPoolDataSource.create -->StandardPoolDataSource.getPooledConnection:返回StandardPooledConnection。
          ?
          ???? StandardPooledConnection通過StandardDataSource.getConnection獲取jdbc driver返回的connection(physical connection),然后通過工廠方法newConnectionHandle采用StandardConnectionHandler對該connection進行包裝。StandardConnectionHandler對PreparedStatement進行重新包裝和Cache,對connection.close進行了控制。
          ?
          4。xapool StandardXAPoolDataSource的getConnection的原理:
          ?? StandardXAPoolDataSource.getConnection -->StandardPoolDataSource.getConnection-->StandardXAPoolDataSource.create -->XADataSource.getXAConnection -->StandardXADatasource.getXAConnection:返回StandardXAConnection。
          ??? StandardXAConnection通過StandardDataSource.getConnection獲取jdbc driver返回的connection(physical connection),然后通過工廠方法newConnectionHandle采用StandardXAConnectionHandle對該connection進行包裝。StandardXAConnectionHandler繼承自StandardConnectionHandler。
          ?
          5。xapool從StandardPoolDataSource獲取的 Connection的關閉原理。
          ?? StandardPooledConnection.close-->StandardConnectionHandler.close(設置closed=true,回收PreparedStatement)-->StandardPooledConnection.closeEvent-->StandardPoolDataSource.connectionClosed-->GenericPool.checkIn(返回連接池)
          ?
          6.xapool中對連接池進行管理的類是GenericPool,該類的checkOut和checkIn方法分別完成連接獲取和連接回收功能。checkOut從unlocked池中獲取可用的連接,如果需要進行檢查或者測試,然后返回;如果發現unlocked池中沒有連接,在連接數小于maxSize的時候調用PoolHelper的實現類創建連接,如果連接數已經達到或者超過maxSize,調用wait使當前進程進入等待狀態(等待期限和等待間隔可以設置),如果等待過程中其他線程釋放了connection返回可用的connection,否則異常:GenericPool:checkOut ERROR? impossible to obtain a new object from the pool
          posted @ 2005-05-17 22:07 dev 閱讀(1820) | 評論 (0)編輯 收藏
           
          1. sleepTime:PoolKeeper檢測時間間隔
          2. lifeTime:連接生命周期(上次訪問時間-當前時間)
          3. deadLockMaxWait(:超過最大連接之后的調用getConnection的等待時間
          4. deadLockRetryWait:超過最大連接之后的調用getConnection等待,在等待中重試的時間間隔
          5. maxSize:連接池的容量

          deald-lock-max-wait和dead-lock-retry-wait的設置要小心,這兩個參數的意義見我的另一個日志:XAPool原理簡要分析。dead-lock-retry-wait最好設置得比較短,這樣不至于線程等待很長時間,dead-lock-max-wait的設置不要太長,一般是設置成比最高并發數下應用處理時間稍長一點,設置過短在大并發下會造成提交實效導致應用數據的丟失,因為超過xapool在超過等待dead-lock-max-wait之后會異常:沒有可用連接分配。

           

          sleepTime是對Connection idle檢測線程PoolKeeper的檢測時間間隔設置。PoolKeeper會定時監測是否存在超過lifeTime的connection然后釋放掉這些connection。不過PoolKeeper在運行的時候會檢查running屬性,以下是它的run方法中的代碼片斷:

            while (! running && !Thread.interrupted()) {
                System.err.println(
          "!!!!"+System.currentTimeMillis());
             
          try {
              synchronized (
          this) {
               wait(
          this.sleepTime); // wait for timeout ms before attack
              }
             } 
          catch (InterruptedException e) {
                                          
          break;
             }
             
          this.pool.cleanUp(); // clean up the Pool and reallocate objects
            }
            
          // release the pool.
            this.pool = null;

          之所以把這段代碼粘出來,是因為running屬性默認是true,而GenericPool在啟動PookKeeper的時候并沒有改變這個值,因此PookKeeper永遠不會運行起來。也許這是xapool的另一個bug:)

          連接池的容量設置是有講究的,一般至少等于AppServer(或者叫WEB 容器)的最大并發數。因為xapool在達到maxSize的時候,如果還有線程需要連接,會進入等待狀態(通過deadLockMaxWait設置最大等待時間,deadLockRetryWait設置等待間隔),在大并發下會造成App Server容器線程池滿,Server在一段時間內(deadLockMaxWait)停止響應的現象。將連接池的容量設置成大于App Server的最大并發數,可以盡可能的避免這種情況。App Server的最大并發數=App Server的線程池線程數,Tomcat默認是75,Websphere默認是50。集群環境下,集群的最大并發數=每臺集群服務器的最大并發數之和

          posted @ 2005-05-17 22:06 dev 閱讀(2400) | 評論 (1)編輯 收藏
           
          現狀:我們的項目中使用了ofbiz2.1,并采用JotmFactory作為TransactionFactory,使用Oracle9i數據庫,在大并發測試的時候發現數據庫游標暴漲并且不釋放,最終導致游標溢出。
           
          原因分析:ofbiz  entityengine的很多操作都是使用PreparedStatement完成的,這無可厚非,問題是JotmFactory采用的是XAPool作為連接池,而XAPool對PreparedStatement進行了Cache,同時Oracle有一個出名的內存漏洞,PreparedStatement使用之后必須關閉,如果不關閉連續進行SQL查詢會造成前面SQL的游標不能釋放;此外JotmConnectionFactory沒有允許對XAPool做更多的配置,按照它使用XAPool的方式,XAPool會對PreparedStatement進行Cache。Oracle漏洞+ofbiz的不周全的使用方式+xapool的機制造成了游標不釋放最終溢出的異常。
           
           
          解決辦法:修改JotmConnectionFactory,調用StandardXAPoolDataSource的setPreparedStmtCacheSize(int)的方法,將preparedStmtCacheSize設置為0。需要注意的是xapool在目前的版本(1.4)當preparedStmtCacheSize=0的時候存在一個bug,close PreparedStatement的時候會報NullPointerException,請參考我的另一個日志XAPool1.4的bug
           
          posted @ 2005-05-17 22:06 dev 閱讀(563) | 評論 (0)編輯 收藏
           
          現狀:XAPool1.4有一個bug,當設置preparedStmtCacheSize=0的時候,關閉連接會拋出NullPointerException
           
          原因:StandardConnectionHandle在Close的時候調用了preparedStatementCache.cleanupAll(),沒有進行判斷;而當preparedStmtCacheSize設置為0的時候,StandardConnectionHandle在setupPreparedStatementCache中把preparedStatementCache設置為null,以下setupPreparedStatementCache是方法中的源代碼片斷:
           
           protected void setupPreparedStatementCache() {
            log.debug(
          "StandardConnectionHandle:setupPreparedStatementCache start");
            
          if (preparedStmtCacheSize == 0) {
             log.debug(
              
          "StandardConnectionHandle:setupPreparedStatementCache return with 0");
             preparedStatementCache 
          = null;
             
          return;
            }
           
          解決辦法:修改setupPreparedStatementCache,如下:
            if (preparedStmtCacheSize == 0) {
             log.debug(
              
          "StandardConnectionHandle:setupPreparedStatementCache return with 0");
          //   preparedStatementCache = null;
             preparedStatementCache = new PreparedStatementCache(0);
             
          return;
            }
          posted @ 2005-05-17 22:05 dev 閱讀(253) | 評論 (0)編輯 收藏
           
          現狀:在我們的項目中使用了Ofbiz2.1,TransactionFactory配置為JotmFactory,數據庫是Oracle9i,lifeTime設置為120000(2分鐘)在大并發測試的時候發現經常Closed Connection的異常。
           
          原因:Oracle數據庫會檢查physical connection的idle時間和使用次數并關閉長時間idle的physical connection,如果應用對從連接池中
          獲取的connection不進行檢查,或者連接池仔返回可用連接之前不進行檢查,在使用過程中就會Closed Connection的異常。大多數數據庫都會檢查physical connection的idle時間。
           
          解決辦法:調用StandardPoolDataSource或者StandardXAPoolDataSource的setCheckLevelObject(int)方法設置連接檢查級別,參數取值如下:
          1. 0:不檢查
          2. 1:對unlocked池中獲取的連接進行Closed檢查
          3. 2:對unlocked池中獲取的連接進行sql測試,需要設置setJdbcTestStmt(Test SQL)
          4. 3:對所有unlocked池中的連接進行Closed檢查
          5. 4:對所有unloked池中的連接進行測試,需要設置setJdbcTestStmt(Test SQL)
           
           
          posted @ 2005-05-17 22:04 dev 閱讀(1138) | 評論 (0)編輯 收藏
          僅列出標題
          共3頁: 上一頁 1 2 3 下一頁 
           
          主站蜘蛛池模板: 大兴区| 宜黄县| 睢宁县| 鹤庆县| 芮城县| 鄢陵县| 临漳县| 三穗县| 临沭县| 灌阳县| 曲水县| 柘荣县| 新竹市| 当涂县| 庆城县| 寿光市| 彩票| 海兴县| 阳朔县| 双柏县| 定州市| 利辛县| 诸城市| 柘荣县| 太仆寺旗| 深泽县| 江源县| 凌海市| 满洲里市| 垦利县| 海阳市| 黑河市| 东乌珠穆沁旗| 出国| 肃宁县| 滨州市| 富宁县| 抚顺市| 定南县| 鹤庆县| 天水市|