隨筆 - 115  文章 - 481  trackbacks - 0
          <2007年3月>
          25262728123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          常用鏈接

          留言簿(19)

          隨筆檔案(115)

          文章檔案(4)

          新聞檔案(1)

          成員連接

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          ????? 作為EJB3.0的一部分,JPA是一個好東西。其簡單的配置方式及強大的默認配置支持,使其可以輕松自由的存在于輕量與重量之間,如果現在您的JavaEE項目,不管是選擇輕量級構架還是重量級構架,如果持久層不選擇使用JPA,而是用一些ORM框架(如Hibernate、TopLink)的專用API,那么在將來的某一天一定會為這個選擇而說出至尊寶那句“假如上天再給我一個機會…”的至理名言。
          ?????? 下面是一個簡單的Entity,是對一個CMS系統中,關于樹狀信息目錄實體類的定義,包括了一些詳細的映射的配置信息。
          @Entity
          public?class?NewsDir?{
          ????@Id
          ????@GeneratedValue(strategy?
          =?GenerationType.TABLE)
          ????
          private?Long?id;//?主鍵

          ????@Column(unique?
          =?true,?nullable?=?false,?length?=?16)
          ????
          private?String?sn;//?目錄編號

          ????
          private?String?title;?//?目錄名稱

          ????@OneToMany(mappedBy?
          =?"parent",?cascade?=?javax.persistence.CascadeType.REMOVE)
          ????
          private?List<NewsDir>?children?=?new?java.util.ArrayList<NewsDir>();//?下級目錄

          ????@ManyToOne
          ????
          private?NewsDir?parent;//?父級目錄



          }

            當然,跟任何其它優秀的技術一樣,JPA也不是完美的,在使用的過程中難免都會出這樣那樣的問題,這就需要我們程序員具有格物致知的本領,在應用中靈活應付這些問題。
            這里例舉一個緩遲加載的問題,以上面的新聞目錄Entity為例。對于parnet與children這個一對多的雙向關聯,為了提高系統效率,children默認使用的是緩遲加載的方式。在一些輕量級的構架中,由于脫離了J2EE容器及事務支持,經常會出現Entity脫離了Persitence Context,變成了detach或EntityManager關閉,導致一些我們預想中的一些功能無法正常運行。
            最常見的就是在使用MVC框架的時候,在表示層無法加載需要緩遲加載的數據。比如,在一個基于EasyJWeb的mvc應用中,action中的方法如下:

          public?Page?doList(WebForm?form,?Module?module)?{
          ????????NewsDirQueryObject?ndqo?
          =?new?NewsDirQueryObject();
          ????????form.toPo(ndqo);
          ????????ndqo.setDel(
          true);
          ????????IPageList?pageList?
          =?service.queryDirsByConditions(ndqo);
          ????????CommUtilForTeaec.saveIPageList2WebForm(pageList,?form);
          ????????form.addResult(
          "dirPath",?this.getDirPath(form));
          ????????
          return?module.findPage("list");
          ????}

          在模板文件中有如下內容:
          #foreach($info in ${dir.children})
          目錄名稱:${info.title}
          #end

          關于業務邏輯層Bean的配置:

          ?

          <aop:config>
          ????????????????
          <aop:pointcut?id="CmsManage"
          ????????????expression
          ="execution(*?com.easyjf.cms.service.*.*(..))"?/>
          <aop:advisor?advice-ref="cmsManageAdvice"
          ????????????pointcut-ref
          ="CmsManage"?/>????????????
          <tx:advice?id="cmsManageAdvice"
          ????????transaction-manager
          ="transactionManager">
          ????????
          <tx:attributes>
          ????????????
          <tx:method?name="get*"?propagation="SUPPORTS"
          ????????????????read-only
          ="true"?/>
          ????????????
          <tx:method?name="query*"?propagation="SUPPORTS"
          ????????????????read-only
          ="true"?/>
          ????????????
          <tx:method?name="*"?propagation="REQUIRED"?/>
          ????????
          </tx:attributes>
          ????
          </tx:advice>
          <bean?id="cmsManageService"
          ????????class
          ="com.easyjf.cms.service.impl.CmsManageServiceImpl">????
          ????????
          <property?name="newsDirDao"?ref="newsDirDao"?/>
          ????
          </bean>

          在這里,當mvc層執行到$!info.getChildren()方法的時候,將會用到緩遲加載,由于Spring的事務是配置在service層的,因此在執行service.queryDirsByConditions方法完成后就關閉了事務。因此運行程序就會出現類似下面的錯誤信息:

          2007-03-28?00:39:35,750?ERROR?[org.hibernate.LazyInitializationException]?-?failed?to?lazily?initialize?a?collection?of?role:?com.easyjf.cms.domain.NewsDir.children,?no?session?or?session?was?closed
          org.hibernate.LazyInitializationException:?failed?to?lazily?initialize?a?collection?of?role:?com.easyjf.cms.domain.NewsDir.children,?no?session?or?session?was?closed
          ?at?org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:
          358)
          ?at?org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:
          350)
          ?at?org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:
          97)

            使用其它的mvc如struts、webwork乃至spring mvc都會有這樣的問題,問題的核心是在事務啟動及結束上,由于我們都習慣于在service層而非mvc配置及使用事務,導致了這樣的問題。解決的辦法其實很簡單,就是把事務的啟動放到mvc層,讓mvc層的controller來開啟事務,而讓業務層的方法加入的事務中。比如,在EasyJWeb中,可以通過如下的配置來實現實現在action中開啟事務:
            在Spring配置文件中配置EasyJWeb的核心處理器,并把process方法添加到事務中,配置文件如下:

          ?

          <aop:config>
          ????????
          <aop:pointcut?id="easyjwebProcessor"
          ????????????expression
          ="execution(*?com.easyjf.web.RequestProcessor.process(..))"?/>
          ????????
          <aop:advisor?advice-ref="txEasyjwebProcessorAdvice"
          ????????????pointcut-ref
          ="easyjwebProcessor"?/>
          ????
          </aop:config>
          ????
          <tx:advice?id="txEasyjwebProcessorAdvice"
          ????????transaction-manager
          ="transactionManager">
          ????????
          <tx:attributes>
          ????????????
          <tx:method?name="*"?propagation="REQUIRED"?read-only="true"?/>
          ????????
          </tx:attributes>
          ????
          </tx:advice>
          ????
          <bean?name="EasyJWeb-Processor"?class="com.easyjf.web.core.DefaultRequestProcessor"/>

            只需要這樣簡單的配置,你會驚奇的發現,所有緩遲加載及其它由Persitence Context無效而引起的問題均解決了。

          ?????? 關于easyjweb與spring的集成,有興趣的朋友請參考stef_wu的《在EasyJWeb使用spring容器》一文。

          (本文作者:EasyJF開源??大峽 歡迎轉載,轉載請保留作者聲明,謝謝!)

          posted on 2007-03-28 02:15 簡易java框架 閱讀(1653) 評論(2)  編輯  收藏

          FeedBack:
          # re: 讓spring幫助你在MVC層解決JPA的緩遲加載問題  2007-03-28 08:37 啊啊啊啊
          解決的辦法其實很簡單,就是把事務的啟動放到mvc層,讓mvc層的controller來開啟事務,而讓業務層的方法加入的事務中。

          何時,對什么啟用事務,取決于該操作是否需要事務。如果的確要將事務加在c層,那么controller中調用的操作必需要是一個事務操作,否則不該回滾的回滾了,這可就麻煩大了  回復  更多評論
            
          # re: 讓spring幫助你在MVC層解決JPA的緩遲加載問題  2007-03-28 09:14 大峽1
          樓上分析得有道理,不過就算在輕量的應用里面,事務其實是很靈活的,給Controller加事務,并不表示業務層所有的事務都必須加入到同一個事務中,如果自己愿意,更不會讓所有的操作回滾。當然,我想這只是解決這一問題方案的一種,如果有更好的方案,歡迎大家提出來研究。  回復  更多評論
            

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 明溪县| 庄河市| 惠州市| 新巴尔虎左旗| 巫溪县| 石楼县| 越西县| 托克托县| 平顶山市| 荆门市| 桐乡市| 伊春市| 迁西县| 措美县| 长葛市| 阿巴嘎旗| 大方县| 辽源市| 金乡县| 当雄县| 潮州市| 上犹县| 原平市| 道孚县| 乌拉特中旗| 屯昌县| 鄯善县| 雷州市| 乌兰察布市| 隆昌县| 高碑店市| 云和县| 大足县| 社旗县| 信阳市| 磐安县| 高碑店市| 海安县| 宣化县| 定边县| 凭祥市|