国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
主題:解惑:在spring+hibernate中,只讀事務(wù)是如何被優(yōu)化的。
/**
*作者:張榮華(ahuaxuan)
*2007-06-28
*轉(zhuǎn)載請(qǐng)注明出處及作者
*/
解惑:在spring+hibernate中,只讀事務(wù)是如何被優(yōu)化的。
 
       大家都知道,spring+hibernate的環(huán)境下,spring對(duì)只讀事務(wù)會(huì)有特別的優(yōu)化,那么spring是如何做到這個(gè)優(yōu)化的呢?      
 
Without ejb中寫到,當(dāng)事務(wù)被標(biāo)識(shí)為只讀事務(wù)時(shí),某些可以針對(duì)只讀事務(wù)進(jìn)行優(yōu)化的資源就可以執(zhí)行相應(yīng)的優(yōu)化措施,比如說hibernate的session在只讀事務(wù)模式下不會(huì)嘗試檢測(cè)和同步持久對(duì)象的狀態(tài)的更新。另外還寫到j(luò)dbc的connection可以通過調(diào)用setReadOnly(true)來切換到只讀事務(wù)模式上來;但是大多數(shù)jdbc driver會(huì)忽略掉他。
 
我們知道spring中所謂的只讀事務(wù)就是通過設(shè)置session的flushmode為never來實(shí)現(xiàn)的(http://www.javaeye.com/topic/87426 )。那么把flushmode設(shè)置為never能給我們帶來什么呢?
我們來看一下hibernate中JDBCTransaction中的方法:
java 代碼
  1. publicvoid commit()  throws  HibernateException {   
  2.         if  (!begun) {   
  3.            thrownew TransactionException( "Transaction not successfully started" );   
  4.        }   
  5.     
  6.        log.debug( "commit" );   
  7.     
  8.         if  ( !transactionContext.isFlushModeNever() && callback ) {   
  9.            transactionContext.managedFlush();  //if an exception occurs during flush, user must call rollback()   
  10.        }   
  11. //也就是在這里會(huì)判斷是否需要刷新一級(jí)緩存中的持久對(duì)象,如果session的flushmode不為//never而且需要回調(diào)的話,那么就刷新一級(jí)緩存中的持久對(duì)象,向數(shù)據(jù)庫(kù)發(fā)送sql語(yǔ)句   
  12.     
  13.        beforeTransactionCompletion();   
  14.         if  ( callback ) {   
  15.            jdbcContext.beforeTransactionCompletion(  this  );   
  16.        }   
  17.     
  18.         try  {   
  19.            commitAndResetAutoCommit();   
  20. //提交事務(wù),并且把事務(wù)的commit方式設(shè)置為auto,是不是和spring在事務(wù)開始和事務(wù)結(jié)束//時(shí)設(shè)置session的flush mode的方式是一樣的呀。   
  21.            log.debug( "committed JDBC Connection" );   
  22.            committed =  true ;   
  23.             if  ( callback ) {   
  24.               jdbcContext.afterTransactionCompletion(  true this  );   
  25.            }   
  26.            afterTransactionCompletion( Status.STATUS_COMMITTED );   
  27.        }   
  28.         catch  (SQLException e) {   
  29.            log.error( "JDBC commit failed" , e);   
  30.            commitFailed =  true ;   
  31.             if  ( callback ) {   
  32.               jdbcContext.afterTransactionCompletion(  false this  );   
  33.            }   
  34.            afterTransactionCompletion( Status.STATUS_UNKNOWN );   
  35.            thrownew TransactionException( "JDBC commit failed" , e);   
  36.        }   
  37.         finally  {   
  38.            closeIfRequired();   
  39.        }   
  40.     }   
我們看一下那個(gè)managedFlush()方法,這個(gè)方法主要就是刷新一級(jí)緩存的一個(gè)方法:
java 代碼
  1. public   void  managedFlush() {   
  2.          if  ( isClosed() ) {   
  3.             log.trace(  "skipping auto-flush due to session closed"  );   
  4.              return ;   
  5.         }   
  6.         log.trace( "automatically flushing session" );   
  7.         flush();   
  8.          //刷新這個(gè)session實(shí)例的一級(jí)緩存。   
  9.          if  ( childSessionsByEntityMode !=  null  ) {   
  10.             Iterator iter = childSessionsByEntityMode.values().iterator();   
  11.              while  ( iter.hasNext() ) {   
  12.                 ( (Session) iter.next() ).flush();   
  13.             }   
  14.         } //刷新該session的子session的一級(jí)緩存。   
  15.     }   
我們知道如果 session flushmode never 的時(shí)候,以上的方法是不會(huì)調(diào)用的,這樣就可以省去很多 flush 的開銷。于是命題就變成了 flush 操作有哪些開銷了。
也許你要問 flush 和不 flush 有什么樣的區(qū)別,在開銷上有多大的區(qū)別呢。要看明白 hibernate 是怎么做 flush 的,那就必須要知道觀察者模式了,實(shí)際上 session 是一個(gè)被觀察者 (subject) ,而真正執(zhí)行 flush 的是一個(gè)觀察者 (observer), 我們來看一下下面這個(gè)圖:
( 這個(gè)圖是我畫在紙上然后用手機(jī)拍下來的 )
 
從這里面我們可以看到 flush 實(shí)際上是由 DefaultFlushEventListener 來執(zhí)行的,而且 sessionimpl 默認(rèn)的只注冊(cè)了一個(gè) FlushEventListener 實(shí)例(為什么只有一個(gè)還要這樣做,我估計(jì)他是為了擴(kuò)展的需要,不知道 3.2 中是否就不止一個(gè)了呢?),這個(gè) DefaultFlushEventListener 最終執(zhí)行了 flush 的方法:
 
java 代碼
  1. public   void  onFlush(FlushEvent event)  throws  HibernateException {   
  2.          final  EventSource source = event.getSession();   
  3.          if  ( source.getPersistenceContext().hasNonReadOnlyEntities() ) {   
  4.                
  5.             flushEverythingToExecutions(event);   
  6. //這個(gè)方法是flush前的準(zhǔn)備工作,它把需要被flush的實(shí)體,集合,等等放到需要被flush   
  7. //的一個(gè)隊(duì)列中   
  8.             performExecutions(source);   
  9. //這個(gè)方法是最重要的,因?yàn)樵谶@里才是真正的執(zhí)行sql語(yǔ)句,并且負(fù)責(zé)更新二級(jí)緩存(如果你//配置了二級(jí)緩存的話)   
  10.             postFlush(source);   
  11. //負(fù)責(zé)flush后的善后工作,比如說一個(gè)對(duì)象不再被另外一個(gè)對(duì)象關(guān)聯(lián)了,那么就把這個(gè)對(duì)象//從一級(jí)緩存重剔除,等等。   
  12.              if  ( source.getFactory().getStatistics().isStatisticsEnabled() ) {   
  13.                 source.getFactory().getStatisticsImplementor().flush();   
  14.             }   
  15.                
  16.         }   
  17.     }   
 
由此我們看到 hibernate 在執(zhí)行 flush 操作的時(shí)候還是做了不少事情的,它不但要把持久對(duì)象刷到數(shù)據(jù)庫(kù),而且還要把其管理的對(duì)象也都刷到數(shù)據(jù)庫(kù)中,這是一個(gè)很大的操作。同時(shí)如果你使用了二級(jí)緩存, flush 操作也會(huì)涉及到它,而且在 flush 時(shí)還要判斷哪些時(shí)插入的,哪些是更新的,哪些是刪除的等等, flush 完了還得更新一級(jí)緩存等。
 
其實(shí)我只是對(duì) flush 作了最簡(jiǎn)單的概括和描述,事實(shí)上從代碼上看來它遠(yuǎn)比我們想象的要來得復(fù)雜的多。
 
在對(duì) flush 簡(jiǎn)單得了解了之后,我們?cè)賮碛懻撘幌拢簽槭裁匆巡樵冊(cè)O(shè)置為只讀事務(wù)。因?yàn)橐粋€(gè)本來只是查詢的操作,卻要在事務(wù)提交時(shí)多做這么多事情,這顯然是不合理的,所以 hibernate 才給 session 的設(shè)置了這么一個(gè) flushmode ,那么只要這個(gè) mode never ,就可以免去這些不必要的操作。而 spring 在對(duì) hibernate 的支持時(shí)也充分的考慮到了這一點(diǎn),所以就把只讀事務(wù)的 session flush mode 設(shè)置為了 never 。這樣我們事務(wù)提交時(shí)就不會(huì)執(zhí)行 flush 操作了。
 
總結(jié):
所以說,我們?cè)谑褂?/span> spring 時(shí)一定要注意把查詢的操作定義成只讀事務(wù),這個(gè)可以給我們帶來不必要的開銷,比如看如下配置。
< property name = "transactionAttributes" >
           < props >
              < prop key = "do*" > PROPAGATION_REQUIRED prop >
              < prop key = "get*" > PROPAGATION_REQUIRED,readOnly prop >
              < prop key = "load*" > PROPAGATION_REQUIRED,readOnly prop >  
              < prop key = "find*" > PROPAGATION_REQUIRED,readOnly prop >
              < prop key = "list*" > PROPAGATION_REQUIRED,readOnly prop >
           props >
property >
 
或者事務(wù)的傳播途徑最好能設(shè)置為 supports (運(yùn)行在當(dāng)前的事務(wù)范圍內(nèi),如果當(dāng)前沒有啟動(dòng)事務(wù),那么就不在事務(wù)范圍內(nèi)運(yùn)行)或者 not supports (不在事務(wù)范圍內(nèi)執(zhí)行,如果當(dāng)前啟動(dòng)了事務(wù),那么掛起當(dāng)前事務(wù)),也就是說查詢操作其實(shí)可以不必要真正的開啟一個(gè)數(shù)據(jù)庫(kù)事務(wù),因?yàn)殚_啟一個(gè)真正的數(shù)據(jù)庫(kù)事務(wù)又會(huì)給我們帶來一點(diǎn)點(diǎn)可以忽略不計(jì)的開銷。下面是一個(gè)例子
< property name = "transactionAttributes" >
           < props >
              < prop key = "do*" > PROPAGATION_REQUIRED prop >
              < prop key = "get*" > PROPAGATION_SUPPORTS,readOnly prop >
              < prop key = "load*" > PROPAGATION_SUPPORTS,readOnly prop >  
              < prop key = "find*" > PROPAGATION_SUPPORTS,readOnly prop >
              < prop key = "list*" > PROPAGATION_SUPPORTS,readOnly prop >
           props >
property >
 

作者:張榮華,未經(jīng)作者同意不得隨意轉(zhuǎn)載!

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
關(guān)于OpenSessionInView
Spring?的OpenSessionInViewFilter簡(jiǎn)介
spring Transaction Manager和hibernate session 吐血經(jīng)驗(yàn)談
spring配置 no matching editors or conversion strategy found 異常解決方案
spring hibernate的事務(wù)處理(使用hibernate原有的sessionFactory)
在Spring中集成Hibernate事務(wù)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服