byterat

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            54 隨筆 :: 0 文章 :: 15 評(píng)論 :: 0 Trackbacks

          #

          spring事務(wù)探索

          原文出處:
          http://www.javaeye.com/topic/11190

          spring自建事務(wù)管理模塊。而且這個(gè)事務(wù)管理是一個(gè)抽象設(shè)計(jì),可以應(yīng)用到很多場(chǎng)合,包括普通的DataSource,jta,jms和hibernate上。

          要正確使用spring的事務(wù),首先需要了解spring在事務(wù)設(shè)計(jì)上的一些概念
          統(tǒng)觀spring事務(wù),圍繞著兩個(gè)核心PlatformTransactionManager和TransactionStatus

          PlatformTransactionManager直譯過(guò)來(lái)就是平臺(tái)相關(guān)事務(wù),這里的平臺(tái)指的是“事務(wù)源”,包括剛才我說(shuō)的DataSource,jta等等。這些無(wú)一不是一個(gè)事務(wù)源。廣義的說(shuō),凡是可以完成事務(wù)性操作的對(duì)象,都可以設(shè)計(jì)出相對(duì)應(yīng)的PlatformTransactionManager,只要這個(gè)事務(wù)源支持commit,rollback和getTransaction語(yǔ)意。

          查看spring代碼,可以發(fā)現(xiàn)這些manager實(shí)現(xiàn)事務(wù),就是調(diào)用事務(wù)源的事務(wù)操作方法

          比如

          HibernateTransactionManager

          代碼

          ?

          1. protected ? void ?doCommit(DefaultTransactionStatus?status)?{ ??
          2. ????????HibernateTransactionObject?txObject?=?(HibernateTransactionObject)?status.getTransaction(); ??
          3. ???????? if ?(status.isDebug())?{ ??
          4. ????????????logger.debug( "Committing?Hibernate?transaction?on?session?[" ?+ ??
          5. ????????????????????txObject.getSessionHolder().getSession()?+? "]" ); ??
          6. ????????} ??
          7. ???????? try ?{ ??
          8. ????????????txObject.getSessionHolder().getTransaction().commit(); ??
          9. ????????} ??
          10. ... ??
          11. ??
          12. ????}??

          jdbc 的DataSourceTransactionManager

          代碼

          ?

          1. protected ? void ?doCommit(DefaultTransactionStatus?status)?{ ??
          2. ????????DataSourceTransactionObject?txObject?=?(DataSourceTransactionObject)?status.getTransaction(); ??
          3. ????????Connection?con?=?txObject.getConnectionHolder().getConnection(); ??
          4. ???????? if ?(status.isDebug())?{ ??
          5. ????????????logger.debug( "Committing?JDBC?transaction?on?connection?[" ?+?con?+? "]" ); ??
          6. ????????} ??
          7. ???????? try ?{ ??
          8. ????????????con.commit(); ??
          9. ????????} ??
          10. ????????... ??
          11. ????}??

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

          總結(jié)上面所說(shuō)的,spring的事務(wù)由PlatformTransactionManager管理,manager最后調(diào)用事務(wù)源的方法來(lái)實(shí)現(xiàn)一個(gè)事務(wù)過(guò)程。而manager通過(guò)TransactionStatus 來(lái)決定如何實(shí)現(xiàn)。

          接下去說(shuō)spring事務(wù)中的TransactionTemplate和TransactionInterceptor

          TransactionTemplate其實(shí)和spring中其他的template的作用類似,起到化簡(jiǎn)代碼的作用,不要被它那么長(zhǎng)的名字嚇倒了,事實(shí)上這個(gè)template并不是什么非常核心的對(duì)象。如果比較學(xué)究派的,可以去看看template設(shè)計(jì)模式,在此就不再對(duì)此贅述了。
          為什么要有TransactionTemplate?先來(lái)看看如果沒(méi)有TransactionTemplate,我們的代碼該怎么寫

          先來(lái)看看spring reference中的一段代碼

          代碼

          ?

          1. DefaultTransactionDefinition?def?=? new ?DefaultTransactionDefinition() ??
          2. def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); ??
          3. ??
          4. TransactionStatus?status?=?transactionManager.getTransaction(def); ??
          5. ??
          6. try ?{ ??
          7. ???? //?execute?your?business?logic?here ??
          8. }? catch ?(MyException?ex)?{ ??
          9. ????transactionManager.rollback(status); ??
          10. ???? throw ?ex; ??
          11. } ??
          12. transactionManager.commit(status);??


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

          代碼

          ?

          1. public ?Object?execute(TransactionCallback?action)? throws ?TransactionException?{ ??
          2. ????????TransactionStatus?status?=? this .transactionManager.getTransaction( this ); ??
          3. ????????Object?result?=? null ; ??
          4. ???????? try ?{ ??
          5. ????????????result?=?action.doInTransaction(status); ??
          6. ????????} ??
          7. ???????? catch ?(RuntimeException?ex)?{ ??
          8. ???????????? //?transactional?code?threw?application?exception?->?rollback ??
          9. ????????????rollbackOnException(status,?ex); ??
          10. ???????????? throw ?ex; ??
          11. ????????} ??
          12. ???????? catch ?(Error?err)?{ ??
          13. ???????????? //?transactional?code?threw?error?->?rollback ??
          14. ????????????rollbackOnException(status,?err); ??
          15. ???????????? throw ?err; ??
          16. ????????} ??
          17. ???????? this .transactionManager.commit(status); ??
          18. ???????? return ?result; ??
          19. ????}??

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

          代碼

          ?

          1. private ? void ?rollbackOnException(TransactionStatus?status,?Throwable?ex)? throws ?TransactionException?{ ??
          2. ???????? if ?(logger.isDebugEnabled())?{ ??
          3. ????????????logger.debug( "Initiating?transaction?rollback?on?application?exception" ,?ex); ??
          4. ????????} ??
          5. ???????? try ?{ ??
          6. ???????????? this .transactionManager.rollback(status); ??
          7. ????????} ??
          8. ???????? catch ?(RuntimeException?ex2)?{ ??
          9. ????????????logger.error( "Application?exception?overridden?by?rollback?exception" ,?ex); ??
          10. ???????????? throw ?ex2; ??
          11. ????????} ??
          12. ???????? catch ?(Error?err)?{ ??
          13. ????????????logger.error( "Application?exception?overridden?by?rollback?error" ,?ex); ??
          14. ???????????? throw ?err; ??
          15. ????????} ??
          16. ????}??


          真相大白,是對(duì)template所持有的某個(gè)transactionManager進(jìn)行回滾。所以如果你的應(yīng)用代碼用的是事務(wù)源a的一些資源,比如到服務(wù)器a的一個(gè)datasource,但是你的transactionManager管理的是另一些資源,比如服務(wù)器b的一個(gè)datasource,代碼鐵定不會(huì)正常運(yùn)行

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

          那么TransactionInterceptor是干什么的?這個(gè)是spring 的聲明式事務(wù)的支持方式。因?yàn)橛肨ransactionTemplate要硬編碼,而且調(diào)整事務(wù)策略很麻煩(不是說(shuō)不能調(diào)。舉個(gè)例子原來(lái)程序拋出異常A需要回滾,現(xiàn)在不需要要,我就可以把a(bǔ) catch吃掉。這時(shí)候template就不會(huì)回滾了。但是每次調(diào)整都要重寫編碼。)而用TransactionInterceptor就可以將這些調(diào)整寫在配置中。我們?cè)賮?lái)挖TransactionInterceptor的代碼

          代碼

          ?

          1. public ?Object?invoke(MethodInvocation?invocation)? throws ?Throwable?{ ??
          2. ???????? //?Work?out?the?target?class:?may?be?null. ??
          3. ???????? //?The?TransactionAttributeSource?should?be?passed?the?target?class ??
          4. ???????? //?as?well?as?the?method,?which?may?be?from?an?interface ??
          5. ????????Class?targetClass?=?(invocation.getThis()?!=? null )???invocation.getThis().getClass()?:? null ; ??
          6. ???????? ??
          7. ???????? //?Create?transaction?if?necessary ??
          8. ????????TransactionInfo?txInfo?=?createTransactionIfNecessary(invocation.getMethod(),?targetClass); ??
          9. ??
          10. ????????Object?retVal?=? null ; ??
          11. ???????? try ?{ ??
          12. ???????????? //?This?is?an?around?advice. ??
          13. ???????????? //?Invoke?the?next?interceptor?in?the?chain. ??
          14. ???????????? //?This?will?normally?result?in?a?target?object?being?invoked. ??
          15. ????????????retVal?=?invocation.proceed(); ??
          16. ????????} ??
          17. ???????? catch ?(Throwable?ex)?{ ??
          18. ???????????? //?target?invocation?exception ??
          19. ????????????doCloseTransactionAfterThrowing(txInfo,?ex); ??
          20. ???????????? throw ?ex; ??
          21. ????????} ??
          22. ???????? finally ?{ ??
          23. ????????????doFinally(txInfo); ??
          24. ????????} ??
          25. ????????doCommitTransactionAfterReturning(txInfo); ??
          26. ??
          27. ???????? return ?retVal; ??
          28. ????}??


          萬(wàn)變不離其宗。

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

          posted @ 2007-03-05 14:45 比特鼠 閱讀(249) | 評(píng)論 (0)編輯 收藏

          2007年已經(jīng)過(guò)去一個(gè)月了, 還沒(méi)有制定今年的規(guī)劃, 現(xiàn)在是時(shí)候了!

          爭(zhēng)取掌握以下技術(shù):

          1. Ruby On Rails?
          進(jìn)一步學(xué)習(xí)ruby的語(yǔ)法和語(yǔ)義,最好能深入到解釋器一層看看有些特性是怎么實(shí)現(xiàn)的。

          2、Spring AOP 及 AspectJ
          個(gè)人覺(jué)得Spring 2.0和AspectJ的結(jié)合,有很多潛力,值得深入挖掘。

          3. Web Service

          4. Java JPA

          5. Role-Based Access Control , Acegi
          buaawhl推薦的,
          http://csrc.nist.gov/rbac/
          http://www.amazon.com/Role-Based-Access-Control-David-Ferraiolo/dp/1580533701/sr=1-1/qid=1161828835/ref=pd_bbs_1/002-1138304-7372032?ie=UTF8&s=books

          下一個(gè)項(xiàng)目的權(quán)限管理會(huì)比較復(fù)雜,以前沒(méi)學(xué)過(guò)這方面的知識(shí)。從Acegi開(kāi)始吧,如果夠用最好。

          6. JBoss JBoss的Cache,AppServer的cluster方面是我比較感興趣的地方,想嘗試一下JBoss應(yīng)用服務(wù)器

          7. 滿足一定條件(比如: 并發(fā)達(dá)1000個(gè)請(qǐng)求)框架Web Application群集部署

          posted @ 2007-02-02 15:28 比特鼠 閱讀(239) | 評(píng)論 (0)編輯 收藏

          關(guān)于Spring屬性編輯器詳解

          原文出處:
          http://stamen.javaeye.com/blog/24660

          最近剛在研究Spring的編輯器,發(fā)現(xiàn)很有意思,剛好galaxystar起了一個(gè)這樣貼,我想對(duì)PropertyEditor作一個(gè)詳細(xì)的整理會(huì)對(duì)大家有益,特定啟了這個(gè)新帖。

          所謂的PropertyEditor,顧名思義,就是屬性編輯器。由于Bean屬性通過(guò)配置文檔以字符串了方式為屬性賦值,所以必須有一個(gè)“東東”負(fù)責(zé)將這個(gè)字符串轉(zhuǎn)換為屬性的直接對(duì)象,如屬性的類型為int,那么編輯器要做的工作就是int i = Integer.parseInt("1");
          Spring為一般的屬性類型提供了默認(rèn)的編輯器,BeanWrapperImpl是Spring框架中重要的類,它負(fù)責(zé)對(duì)注入的Bean進(jìn)行包裝化的管理,常見(jiàn)屬性類型對(duì)應(yīng)的編輯器即在該類中通過(guò)以下代碼定義:

          代碼

          但是,并非Bean的屬性都是這些常見(jiàn)的類型,如果你的Bean需要注入一個(gè)自定義類型的屬性,而又想享受IoC的好處,那么就只得自己開(kāi)干,提供一個(gè)自定義的PropertyEditor了。
          下面,分幾個(gè)步驟來(lái)說(shuō)明,定義一個(gè)自定義PropertyEditor的過(guò)程。
          1)首先,碰到的問(wèn)題即是,要如何編輯自己的PropertyEditor,其實(shí)需要了解一點(diǎn)java.beans包的知識(shí),在該包中,有一個(gè)java.beans.PropertyEditor的接口,它定義了一套接口方法(12個(gè)),即通過(guò)這些方法如何將一個(gè)String變成內(nèi)部的一個(gè)對(duì)象,這兩個(gè)方法是比較重要的:
          a)setValue(Object value) 直接設(shè)置一個(gè)對(duì)象,一般不直接用該方法設(shè)置屬性對(duì)象
          b)setAsText(String text) 通過(guò)一個(gè)字符串來(lái)構(gòu)造對(duì)象,一般在此方法中解析字符串,將構(gòu)造一個(gè)
          類對(duì)象,調(diào)用setValue(Object)來(lái)完成屬性對(duì)象設(shè)置操作。

          2)實(shí)現(xiàn)所有的接口方法是麻煩的,java.beans.PropertyEditorSupport 適時(shí)登場(chǎng),一般情況下,我們通過(guò)擴(kuò)展這個(gè)方便類即可。

          3)編寫完后,就是在Spring配置文件中注冊(cè)該屬性類型編輯器的問(wèn)題,Spring提供了專門的注冊(cè)工具類
          org.springframework.beans.factory.config.CustomEditorConfigurer,它負(fù)責(zé)將屬性類型和
          屬性編輯器關(guān)聯(lián)起來(lái)。到時(shí)BeanFactory注入Bean的屬性時(shí),即會(huì)在注冊(cè)表中查找屬性類型對(duì)應(yīng)的編輯器。

          下面給出一個(gè)小例子,例子先作一個(gè)簡(jiǎn)單描述:
          1)Person 需要進(jìn)行屬性注入的Bean,有兩個(gè)屬性 一個(gè)是name,一個(gè)是address Address是一個(gè)類
          2)Address Person的屬性類型,本身有3個(gè)屬性。
          3)AddressPropertyEditor Address類型對(duì)應(yīng)的屬性編輯器。

          開(kāi)工:
          1.Person.java

          代碼

          2.Address.java
          代碼


          AddressPropertyEditor.java
          代碼

          打開(kāi)Spring配置文件,添上這兩個(gè)配置項(xiàng):

          代碼

          ?

          下面是我自己寫的日期轉(zhuǎn)換類:

          我的配置:
          posted @ 2007-01-20 21:21 比特鼠 閱讀(412) | 評(píng)論 (0)編輯 收藏

          Error convertoring HTML to XHTML: System.ArgumentException: Cannot have ']]>' inside an XML CDATA block. at System.Xml.XmlTextWriter.WriteCData(String text) at System.Xml.XmlWriter.WriteNode(XmlReader reader, Boolean defattr) at FreeTextBoxControls.Support.Formatter.HtmlToXhtml(String input)
          posted @ 2007-01-19 16:51 比特鼠 閱讀(209) | 評(píng)論 (0)編輯 收藏

          原文出自: http://www.aygfsteel.com/waterye/archive/2005/08/23/10836.aspx

          OpenSessionInView模式

          Spring+Hibernate中,? 集合映射如果使用lazy="true", 當(dāng)PO傳到View層時(shí), 出現(xiàn)未初始化session已關(guān)閉的錯(cuò)誤,只能在dao先初始化
          parent.getChilds().size();

          Spring提供Open Session In View來(lái)解決這個(gè)問(wèn)題, 有兩種方式
          1. Interceptor
          ??? <!-- ?===========?OpenSession?In?View?pattern?============== -->
          ????
          < bean? id ="openSessionInViewInterceptor"
          ??????????class
          ="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor" >
          ????????
          < property? name ="sessionFactory" ?ref ="sessionFactory" />
          ????
          </ bean >

          ????
          < bean? id ="urlMapping" ?class ="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping" >
          ????????
          < property? name ="interceptors" ?ref ="openSessionInViewInterceptor" />
          ????????
          < property? name ="mappings" >
          ????????????
          < props >
          ??????????? ......
          ????????????
          </ props >

          ????????
          </ property >
          ????
          </ bean >
          2. Filter
          < web-app >
          ?
          < filter >
          < filter-name > hibernateFilter </ filter-name >
          < filter-class >
          org.springframework.orm.hibernate.support.OpenSessionInViewFilter
          </ filter-class >
          </ filter >
          ?
          < filter-mapping >
          < filter-name > hibernateFilter </ filter-name >
          < url-pattern > *.do </ url-pattern >
          </ filter-mapping >

          </ web-app >

          說(shuō)明: 個(gè)人更喜歡用Interceptor方式, filter是在web.xml中定義
          有了OpenSessionInView,并不是一切就ok了。簡(jiǎn)單的crud可以,但對(duì)于復(fù)雜業(yè)務(wù)邏輯就要想點(diǎn)法子。

          OSIV默認(rèn)是request per session的, 所以即使沒(méi)有顯式update(po),Hibernate也會(huì)幫你保存的,dao的業(yè)務(wù)判斷就無(wú)效,還好有evict()可用。
          update code
          // Controller
          public
          ?ModelAndView?update()?{
          ????p?
          =
          ?dao.getVo(id);
          ????bindObject(request);
          ????dao.update(p);
          }

          // Dao
          public
          ?Object?getVo(id)?{
          ????p?
          =
          ?getHibernateTemplate().get(clazz,?id);
          ????p.getChilds().size();
          ????getHibernateTemplate().evict(p);
          ????
          return
          ?p;
          }

          public ? void
          ?update(p)?{
          ????oldP?
          =
          ?getVo(id);
          ????
          // ?++--(oldP);

          ????getHibernateTemplate().update(p);
          ????
          // ?++--(p);

          }
          posted @ 2007-01-19 15:33 比特鼠 閱讀(308) | 評(píng)論 (0)編輯 收藏

          例如:
          <class name="User" table="user">
          <id name="id" column="id" type="java.lang.Long">
          <generator class="native"/>
          </id>

          generator標(biāo)識(shí)符生成器 描述

          increment   ???適用于代理主鍵。由Hibernate自動(dòng)以遞增方式生成
          identity    ??適用于代理主鍵。由底層數(shù)據(jù)庫(kù)生成標(biāo)識(shí)符
          sequence    ??適用于代理主鍵。Hibernate根據(jù)底層數(shù)據(jù)庫(kù)的序列生成標(biāo)識(shí)符,這要求底層數(shù)據(jù)庫(kù)支持序列
          hilo      ???適用于代理主鍵。Hibernate分局high/low算法生成標(biāo)識(shí)符
          seqhilo     ??適用于代理主鍵。使用一個(gè)高/低位算法來(lái)高效的生成long,short或者int類型的標(biāo)識(shí)符。
          native     ???適用于代理主鍵。根據(jù)底層數(shù)據(jù)庫(kù)對(duì)自動(dòng)生成標(biāo)識(shí)符的方式,自動(dòng)選擇identity、sequence或hilo
          uuid.hex    ???適用于代理主鍵。Hibernate基于128 位UUID 算法生成16 進(jìn)制數(shù)值(編碼后以長(zhǎng)度32 的字符串表示)
          uuid.string  ????適用于代理主鍵。與uuid.hex 類似,只是生成的主鍵未進(jìn)行編碼(以長(zhǎng)度16 的字符串表示),不能應(yīng)用在 PostgreSQL 數(shù)據(jù)庫(kù)中
          assigned    ???適用于自然主鍵。由Java應(yīng)用程序負(fù)責(zé)生成標(biāo)識(shí)符
          foreign     ???適用于代理主鍵。使用另外一個(gè)相關(guān)聯(lián)的對(duì)象的標(biāo)識(shí)符

          以下舉例:
          1、指定參數(shù)的情況:
          ??? <id name="id" unsaved-value="0">
          ????? <generator class="sequence">
          ??????? <param name="sequence">SEQ_CHILD</param>
          ????? </generator>
          </id>
          使用的是sequence,適合oracle數(shù)據(jù)庫(kù);


          2、對(duì)于sql server2000中的數(shù)據(jù)庫(kù)子增字段,在配置文件使用下列方法實(shí)現(xiàn):
          <id name="id" type="long" unsaved-value="0">
          ???? <column name="id" sql-type="numeric" not-null="true" />
          ???? <generator class="identity" />
          </id>
          這里主要是:identity:代表由sql server2000數(shù)據(jù)庫(kù)自己提供子增字段.如果要hibernate自己提供,則用increment關(guān)鍵字來(lái)實(shí)現(xiàn)


          3、如果表中的主鍵用字符串類型:可以用hibernate自己提供的方法實(shí)現(xiàn)主鍵唯一:
          ? <id name="id" type="string" unsaved-value="null">
          ????? <column name="cid" sql-type="char(32)" not-null="true" />
          ????? <generator class="uuid.hex" />
          ? </id>
          使用的是uuid.hex: 采用128位的算法來(lái)生成一個(gè)32位字符串。最通用的一種方式。適用于所有數(shù)據(jù)庫(kù)。


          重要的知識(shí)點(diǎn):
          1. 如果有部門表,有員工表,員工表中有dep_id,則表部門類和員工類是one-to-many的關(guān)系:
          ?? 可以使用:? ( 在部門類department中使用下列)
          ?? Department類:?
          ???? /**? 部門的所有員工?? */
          ??? private Set staffs = new TreeSet();
          ???
          ??? xml的文件:
          ????? <set name="staffs" >
          ????????? <key column="dep_id"/>
          ????????? <one-to-many class="hbp.sys.data.Staff"/>
          ????? </set>
          ????? 如果是list,需要用索引<index> </index>,具體其中的含義,不是很明白.待以后研究
          ?????
          ?2. 如果部門要有一個(gè)負(fù)責(zé)人,即部門表(tb_department)中有一個(gè)字段:staff_id.
          ???? 那么表示部門和負(fù)責(zé)人之間的關(guān)系是many-to-one的關(guān)系
          ???? Department類:
          ????? /** 部門負(fù)責(zé)人id */
          ??? private Staff staff;
          ???
          ??? xml 文件
          ???? <many-to-one name="staff" class="hbp.sys.data.Staff"? column="staff_id"/>?
          ?
          ?3. 多對(duì)多關(guān)系,一般我們是做一個(gè)中間關(guān)聯(lián)表.我用角色和權(quán)限做了個(gè)例子,
          ????? Right(id,name)???? Role(id,name)?? 中間表:tb_role_right(role_id,right_id)
          ????? Right類中有一個(gè)Role的集合:private Set roles=new TreeSet();
          ????? Role類中也有一個(gè)Right的集合:private Set rights=new TreeSet();
          ????? 則兩者是明顯的多對(duì)多關(guān)系.使用many-to-many來(lái)實(shí)現(xiàn);
          ????? xml文件中
          ????? right.hbm.xml:如下:
          ??????? <set name="roles" table="tb_role_right" cascade="all">
          ?????????? <key column="right_id"/>
          ?????????? <many-to-many column="role_id" class="hbp.sys.data.Role"/>
          ??????? </set>
          ????? role.hbm.xml文件中類似:
          ??????? <set name="rights" table="tb_role_right" cascade="all">
          ????????? <key column="role_id"/>
          ????????? <many-to-many column="right_id" class="hbp.sys.data.Right"/>
          ??????? </set>


          4. 幾個(gè)值得注意的問(wèn)題:
          ??????? a)在xml?映射文件中,寫類的名字時(shí)一定用類的全名:即:包+類名如:(hbp.sys.data.Staff),這個(gè)錯(cuò)誤使我費(fèi)了半天勁.:(
          ??????? b)我在寫實(shí)現(xiàn)基本DAO操作時(shí),寫了
          ???????????? session.delete("from Right as right where right.id="+id);?
          ???????????? 程序死活報(bào)錯(cuò),我折騰了半天,跟蹤到底,才恍然大悟,hibernate在解析sql語(yǔ)句的時(shí)候把
          ???????????? 其中的right,當(dāng)成了數(shù)據(jù)庫(kù)中的右連接("保留字"),唉,這種關(guān)鍵字,不能隨便用啊,:)


          5. hibernate中HQL語(yǔ)言的查詢根據(jù)你的sql的不同而返回不同的對(duì)象類型.
          ???????? 如果你使用session.find(String hql)
          ???????? 一般會(huì)返回一個(gè)List,如:from Staff staff;返回的是包含所有的員工對(duì)象的集合
          ???????? 如你的hql為:select count(*) from Staff staff;則返回的是一個(gè)Integer對(duì)象
          ???????? 如果你使用的hql為:select count(distinct staff.name),count(*) from Staff staff;則返回的是一個(gè)Object
          ???????? 即Object[],需要先把他轉(zhuǎn)換成Object[],然后在取[0],[1].
          ???????? 這種設(shè)計(jì)我不知道hibernate是如何處理的,感覺(jué)既好也不好.好的是可以使用一個(gè)find獲得任意查詢
          ???????? 不好在于根據(jù)hql來(lái)處理返回結(jié)果,容易出錯(cuò).

          posted @ 2007-01-18 10:44 比特鼠 閱讀(2086) | 評(píng)論 (0)編輯 收藏

          <標(biāo)識(shí)符>在理論上來(lái)說(shuō)可以是自由命名的,但每個(gè)頭文件的這個(gè)“標(biāo)識(shí)”都應(yīng)該是唯一的。標(biāo)識(shí)的命名規(guī)則一般是頭文件名全大寫,前后加下劃線,并把文件名中的“.”也變成下劃線,如:stdio.h

          #ifndef _STDIO_H_?????????? //如果沒(méi)有定義_STDIO_H_
          #define _STDIO_H_? 1??????? //則定義_STDIO_H_, 值為 1


          1. 如果沒(méi)有定義<標(biāo)識(shí)符>, 則定義<標(biāo)識(shí)符>
          #ifndef <標(biāo)識(shí)符>
          #ifdefine <標(biāo)識(shí)符> <標(biāo)識(shí)符值>
          ..
          ..
          #endif



          2. 如果沒(méi)有定義<標(biāo)識(shí)符>, 則預(yù)編譯程序段1, 否則編譯程序段2

          #ifndef <標(biāo)識(shí)符>?
          ????
          程序段1
          ?
          #else

          ????
          程序段2
          ?
          #endif

          3. 如果表達(dá)式的值不為0, 則編譯程序段1, 否則編譯程序段2

          #if 表達(dá)式
          ????
          程序段1
          ?
          #else

          ????
          程序段2
          ?
          #endif


          posted @ 2007-01-10 10:46 比特鼠 閱讀(306) | 評(píng)論 (0)編輯 收藏

               摘要: JS的正則表達(dá)式 //校驗(yàn)是否全由數(shù)字組成 代碼 function?isDigit(s) ?? ...  閱讀全文
          posted @ 2006-12-20 21:49 比特鼠 閱讀(227) | 評(píng)論 (0)編輯 收藏



          正則表達(dá)式測(cè)試(V0.1)

          表達(dá)式:
          測(cè)試值:
          輸出值:
          標(biāo)??識(shí): 全局??忽略??多行 ? 方??法:
          ????????


          posted @ 2006-12-20 21:40 比特鼠 閱讀(623) | 評(píng)論 (0)編輯 收藏

          正則表達(dá)式用于字符串處理,表單驗(yàn)證等場(chǎng)合,實(shí)用高效,但用到時(shí)總是不太把握,以致往往要上網(wǎng)查一番。我將一些常用的表達(dá)式收藏在這里,作備忘之用。本貼隨時(shí)會(huì)更新。

          匹配中文字符的正則表達(dá)式: [\u4e00-\u9fa5]

          匹配雙字節(jié)字符(包括漢字在內(nèi)):[^\x00-\xff]

          應(yīng)用:計(jì)算字符串的長(zhǎng)度(一個(gè)雙字節(jié)字符長(zhǎng)度計(jì)2,ASCII字符計(jì)1)

          String.prototype.len=function(){return this.replace([^\x00-\xff]/g,"aa").length;}

          匹配空行的正則表達(dá)式:\n[\s| ]*\r

          匹配HTML標(biāo)記的正則表達(dá)式:/<(.*)>.*<\/\1>|<(.*) \/>/

          匹配首尾空格的正則表達(dá)式:(^\s*)|(\s*$)

          應(yīng)用:javascript中沒(méi)有像vbscript那樣的trim函數(shù),我們就可以利用這個(gè)表達(dá)式來(lái)實(shí)現(xiàn),如下:

          String.prototype.trim = function()
          {
          ??? return this.replace(/(^\s*)|(\s*$)/g, "");
          }

          利用正則表達(dá)式分解和轉(zhuǎn)換IP地址:

          下面是利用正則表達(dá)式匹配IP地址,并將IP地址轉(zhuǎn)換成對(duì)應(yīng)數(shù)值的javascript程序:

          function IP2V(ip)
          {
          ?re=/(\d+)\.(\d+)\.(\d+)\.(\d+)/g? //匹配IP地址的正則表達(dá)式
          if(re.test(ip))
          {
          return RegExp.$1*Math.pow(255,3))+RegExp.$2*Math.pow(255,2))+RegExp.$3*255+RegExp.$4*1
          }
          else
          {
          ?throw new Error("Not a valid IP address!")
          }
          }

          不過(guò)上面的程序如果不用正則表達(dá)式,而直接用split函數(shù)來(lái)分解可能更簡(jiǎn)單,程序如下:

          var ip="10.100.20.168"
          ip=ip.split(".")
          alert("IP值是:"+(ip[0]*255*255*255+ip[1]*255*255+ip[2]*255+ip[3]*1))

          匹配Email地址的正則表達(dá)式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*

          匹配網(wǎng)址URL的正則表達(dá)式:http://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?

          利用正則表達(dá)式去除字串中重復(fù)的字符的算法程序:[注:此程序不正確,原因見(jiàn)本貼回復(fù)]

          var s="abacabefgeeii"
          var s1=s.replace(/(.).*\1/g,"$1")
          var re=new RegExp("["+s1+"]","g")
          var s2=s.replace(re,"")
          alert(s1+s2)? //結(jié)果為:abcefgi

          我原來(lái)在CSDN上發(fā)貼尋求一個(gè)表達(dá)式來(lái)實(shí)現(xiàn)去除重復(fù)字符的方法,最終沒(méi)有找到,這是我能想到的最簡(jiǎn)單的實(shí)現(xiàn)方法。思路是使用后向引用取出包括重復(fù)的字符,再以重復(fù)的字符建立第二個(gè)表達(dá)式,取到不重復(fù)的字符,兩者串連。這個(gè)方法對(duì)于字符順序有要求的字符串可能不適用。

          得用正則表達(dá)式從URL地址中提取文件名的javascript程序,如下結(jié)果為page1

          s="http://www.9499.net/page1.htm"
          s=s.replace(/(.*\/){0,}([^\.]+).*/ig,"$2")
          alert(s)

          利用正則表達(dá)式限制網(wǎng)頁(yè)表單里的文本框輸入內(nèi)容:

          用正則表達(dá)式限制只能輸入中文:onkeyup="value=value.replace(/[^\u4E00-\u9FA5]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\u4E00-\u9FA5]/g,''))"

          用正則表達(dá)式限制只能輸入全角字符:?onkeyup="value=value.replace(/[^\uFF00-\uFFFF]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\uFF00-\uFFFF]/g,''))"

          用正則表達(dá)式限制只能輸入數(shù)字:onkeyup="value=value.replace(/[^\d]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))"

          用正則表達(dá)式限制只能輸入數(shù)字和英文:onkeyup="value=value.replace(/[\W]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))"

          posted @ 2006-12-20 21:25 比特鼠 閱讀(277) | 評(píng)論 (0)編輯 收藏

          僅列出標(biāo)題
          共6頁(yè): 上一頁(yè) 1 2 3 4 5 6 下一頁(yè) 
          主站蜘蛛池模板: 旬阳县| 和龙市| 祥云县| 清流县| 宜宾县| 红安县| 镶黄旗| 广东省| 麻栗坡县| 上栗县| 个旧市| 鄂托克旗| 麻城市| 夹江县| 庆城县| 革吉县| 安吉县| 大庆市| 新民市| 平阴县| 平和县| 九台市| 邢台县| 维西| 华蓥市| 沂源县| 女性| 册亨县| 南平市| 张北县| 徐闻县| 晋城| 临清市| 两当县| 宝丰县| 三台县| 沭阳县| 泰和县| 广宁县| 儋州市| 揭东县|