亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Java EE/J2EE面向?qū)ο髮崙?zhàn)之道

系統(tǒng) 1879 0

OO思維


  經(jīng)??吹讲簧偃吮г笿ava EE/J2EE中配置太復(fù)雜,煩瑣,不簡單易學(xué),其實所謂簡單易學(xué)是取決于你是否有OO思維方式。

  分層架構(gòu)是面向?qū)ο驩O在企業(yè)軟件中應(yīng)用的標(biāo)志,目前一個企業(yè)軟件系統(tǒng)包括表現(xiàn)層、業(yè)務(wù)層和持久層,那么分層架構(gòu)和OO關(guān)系是如何?

  表現(xiàn)層的界面表單中通常是一些離散數(shù)據(jù),也就是單個字段數(shù)據(jù),通過Struts等框架提供ActionForm以及標(biāo)簽庫,將這些單個字段數(shù)據(jù)封裝起來和業(yè)務(wù)層的Domain Model進行了映射,因此,表現(xiàn)層的主要編程工作就是映射配置。

  持久層是將Domain Model對象保存到數(shù)據(jù)庫中,過去使用JDBC,我們要逐個打開這些Model對象,然后每個字段逐個 保存到數(shù)據(jù)庫中,如果說表現(xiàn)層框架是實現(xiàn)離散數(shù)據(jù)封裝,那么持久層實現(xiàn)的是反方向:拆封。Hibernate是一個持久層O/R mapping框架, 也就是在對象和關(guān)系數(shù)據(jù)庫之間進行映射的框架,EJB的CMP也是類似道理,因此,持久層的主要編程工作也是映射配置。

  表現(xiàn)層和持久層這種配置工作就如同打包郵寄一樣:你首先要將你的單件用一個箱子包裝起來,達到目的地,這個箱子被打開,單件被逐步取出。表現(xiàn)層和持久層這樣做的目的是保證中間業(yè)務(wù)層完全面向?qū)ο螅WC業(yè)務(wù)層完全是和一個個對象模型打交道。

  在一個真正面向?qū)ο蟮南到y(tǒng)中,表現(xiàn)層和持久層是為了將非對象化的數(shù)據(jù)轉(zhuǎn)為對象。因此,在先進的JavaEE/J2EE架構(gòu)中,表現(xiàn)層和持久層的主要工作就是配置工作,而且主要是映射mapping的配置。

  下面的問題就是:如何解決映射配置簡單而且易用,如果擁有正確的指導(dǎo)配置的思維,那么配置工作就容易簡單多, 否則,就倍感配置復(fù)雜。 那些感覺Java配置復(fù)雜的人其實他并沒有完整的OO思維。為什么這么說呢?以O(shè)RM(Hibernate)配置簡易方式說明:



配置的簡要之道

  首先,配置是映射XML配置,顧名思義,也就是在兩者之間做協(xié)調(diào),牽線搭橋,說白了,就是做紅娘,但和做紅娘又有些區(qū)別,做紅娘可以要求雙方做些改變,互相遷就,但是做映射配置,則不能這樣,因為那樣做就可能做出和需求要求不一樣的東西。

  配置的簡要之道就是:圍繞對象模型進行配置;而不是圍繞數(shù)據(jù)表進行配置。

  以持久層映射配置來說:存在Domain Model對象和關(guān)系數(shù)據(jù)表,如果感覺在兩者之間配置映射很困難,雙方做些改變,但是有可能 需求不答應(yīng),你一旦為協(xié)調(diào)而作出的改變可能偏離需求實現(xiàn)的目標(biāo),最后作出的系統(tǒng)面貌全非,根本不是客戶所需要的。

  那么怎么辦?很顯然,緊扣需求,反映需求的那一方堅決不要變動,那么Domain Model和關(guān)系數(shù)據(jù)表哪一方反映需求呢?按照OO分析,當(dāng)然 是Domain Model,Model對象我們是依據(jù)Evans Model等模型驅(qū)動設(shè)計MDD概念設(shè)計出來,他們是需求的代表。

  很顯然,我們的映射配置必須順著Model對象這個思維來配,對于名詞式的Model,關(guān)聯(lián)無外乎是其主要關(guān)系,當(dāng)然還有繼承,因此,象Hibernate 這些映射配置語法也是面向這些主要對象關(guān)系的。

  表現(xiàn)層配置也是同樣的道理,需要將Domain Model配置成界面表單,在實際中,我們有可能采取的是通過界面收集需求,因此,這個映射配置過程也是考驗Model對象是否提煉正確與否,有可能發(fā)現(xiàn)Model不能實現(xiàn)一些界面需求功能,這時反過來必須修改我們的Model,而不是僅僅在表現(xiàn)層這個技術(shù)層面做些補救措施就糊弄過去。

  Java EE/J2EE系統(tǒng)開發(fā)過程 敏捷的迭代是必然的。沒有一個天才能夠一步到位提煉出兼顧界面和數(shù)據(jù)表以及需求的統(tǒng)一模型出來。

  總之,完成一個真正面向?qū)ο蟮腏ava EE/J2EE系統(tǒng),必須抓住領(lǐng)域建模和具體框架熟練配置兩點,只有這樣才能保證Java項目成功實施。最關(guān)鍵的是提煉出反映出業(yè)務(wù)系統(tǒng)的領(lǐng)域模型:Domain Model,完成業(yè)務(wù)建模后,就是依賴Struts/Hibernate等配置分配將Model 映射到界面和數(shù)據(jù)庫,其實就是將業(yè)務(wù)模型移植到計算機領(lǐng)域并能夠正確運行。?



高聚合和低關(guān)聯(lián)


  如果一個系統(tǒng)都被設(shè)計成相互沒有任何不包含的單個對象,很顯然是不能正確反映實際需求的,萬事萬物都是有其部分組成的,例如窗戶由玻璃和框架組成,人是由胳膊 腿等身體部分組成,現(xiàn)實世界中,事物之間總是存在關(guān)系,聚合和組成是最常見的。

?? ??例如訂單,一個訂單Orders中由客戶名稱和地址,訂購的產(chǎn)品品種和數(shù)量,客戶名稱和地址我們可以抽象為Customer來代表,產(chǎn)品我們使用Product來代表,由于一個訂單中可能訂購了多個產(chǎn)品,很顯然,一個訂單對象中應(yīng)該有多個Product對象,而且每個Product的數(shù)量不一樣,我們將Product和其數(shù)量再抽象包裝成OrderLine訂單條目對象,這樣,訂單中包含多個訂單條目,而且訂單條目只有依賴某個訂單,是其組成部分,是一種強聚合關(guān)系,不是普通的聚合或關(guān)聯(lián)關(guān)系。而Customer和Order之間是一種聚合關(guān)系,如果訂單沒有客戶信息,就不成為訂單了。 Java EE/J2EE面向?qū)ο髮崙?zhàn)之道



?? ? 下面再以用戶User這個對象為例,用戶User可能擁有很多動態(tài)屬性,一些屬性需要運行時動態(tài)確定,用戶和動態(tài)屬性是一個整體和部分的聚合關(guān)系;每個用戶都必然屬于某個部門,因此,用戶和部門屬性對象之間也是一個整體和部分的聚合關(guān)系,這兩種聚合關(guān)系不同之處在于:前者一個用戶可能有多個動態(tài)屬性,是1:N關(guān)系;部門Dept和用戶User之間是1:N關(guān)系,一個部門中可能有多個用戶,反過來說,對于用戶User來說:它和部門Dept之間是N:1關(guān)系。



Java EE/J2EE面向?qū)ο髮崙?zhàn)之道
?


?? ? ?通過以上建模過程,我們基本搞清楚兩件事:這個領(lǐng)域中存在哪些模型對象?按照Evans的DDD理論,哪些是實體,哪些是值對象;然后我們必須搞清楚那些聚合關(guān)系,他們是整體部分的關(guān)系,用來共同組成一個完整對象的。

?


?

持久層Hibernate聚合實現(xiàn)


  在持久層我們需要做的主要工作就是將上述Domain Model 進行持久化映射配置,以User為例,User是一個實體,我們配置User.hbm.xml如下:

?

    
      <hibernate-mapping>
  <class name="sample.model.User" table="testuser">
    <id name="userId" type="java.lang.String" >
    <generator class="assigned"/>
  </id>

  <property name="username" type="java.lang.String">
    <column name="name" />
  </property>

  <!--表示和部門Dept之間是一種多對一關(guān)系 --> 
   <many-to-one cascade="save-update" name="dept" 
     class="sample.model.Dept" column="categoryId" />

  <!-- 表示和用戶屬性UserPropperty之間是一種1對多關(guān)系--> 
  <bag name="userProps" inverse="true" cascade="all" >
    <key column="userId" />
    <one-to-many class="sample.model.UserProperty" />
  </bag>  
</class>



</hibernate-mapping>
    
  

?


?

  ? 在User的映射配置文件中,我們很自然地表達了上節(jié)Model之間的聚合關(guān)系,通過Hibernate配置,我們將模型對象之間的關(guān)系可以持久化保存到數(shù)據(jù)庫中了,也就是可以永久維持這種關(guān)系,實際上,現(xiàn)實世界中也是這樣的,部分和整體的關(guān)系是一直存在,除非這個整體這個對象不存在,而且修改部分對象內(nèi)部值,必須通過整體這個對象。

  在user配置中,我們并沒有去做任何關(guān)系數(shù)據(jù)表testuser的設(shè)計和設(shè)定,因為我們知道,當(dāng)User.hbm.xml配置完成后,這個J2EE系統(tǒng)部署發(fā)布到J2EE容器中時,Hibernate會根據(jù)這個配置自動創(chuàng)建數(shù)據(jù)表testuser,數(shù)據(jù)表的建立已經(jīng)是一個部署調(diào)試階段的、技術(shù)層面的具體工作。

?

?

?

Hibernate重要的父子關(guān)系

  Hibernate在處理User和UserProperty這樣一對多的父子關(guān)系時,具體實現(xiàn)起來要有一些具體細節(jié)必須注意,而且Hibernate2和Hibernate3兩個版本是不一樣的:

  當(dāng)我們需要只通過一句話session.save(user)或session.update(user)就能完成User和它其中多個Userproperty都能自動保存或更新時(必須指定cascade="all" 或save-update),尤其是update(user)更新時,其子集合userProps屬性中可能有一些Userproperty是修改過的,一些Userproperty則是新增的,對于新增要使用insert語句;而對于修改則使用update語句,當(dāng)我們籠統(tǒng)地調(diào)用一句update(user)時,那么Hibernate是如何判斷這個user中子集合中哪些是修改?哪些是新增的?

  Hibernate是通過主鍵來判斷的,也就是說,通過UserProperty的主鍵來判斷該對象是修改?還是新增。最關(guān)鍵的是:這個主鍵必須由Hibernate自動產(chǎn)生,如果你想自己指定子對象UserProperty主鍵,那么就有可能很多麻煩,這個麻煩是出其的麻煩,無法判斷具體原因。所以,在簡單方便的道路上邁錯一步就是萬丈深淵。下面是UserProperty的映射配置:

?


?

    
      <hibernate-mapping>

  <class name="sample.model.UserProperty" table="userprops">
    <id name="propId" type="java.lang.String" >
      <generator class="uuid.hex"/><!-- 不能為assigned--> 
    </id>  
  <property name="name" />  
  <property name="value" />

  <!-- 為提升性能而設(shè)定 --> 
  <many-to-one name="user" column="userId" not-null="true"/> 
</class>

</hibernate-mapping>
    
  

?

?

?

?? ? ?注意:以上配置只適合Hibernate 3.0以上版本,如果是Hibernate 2,那么必須在 :

<id name="propId" type="java.lang.String" >

中加入unsaved-value="null",而且這個值是null還是0或-1,取決你的主鍵類型:

<id name="propId" type="java.lang.String" unsaved-value="null">

  是不是感覺Hibernate2太麻煩了!在Hibernate3中,就沒有這個規(guī)定了,所以,如果當(dāng)初使用Hibernate2來實現(xiàn)J2EE的oo簡潔實現(xiàn)之道,還存在技術(shù)上的困難和難點。

  Hibernate2和Hibernate3在處理父子關(guān)系上,還有一個不同就是lazy設(shè)定上:Hibernat2缺省lazy是false,當(dāng)通過load將User獲取以后,在session關(guān)閉以后,你可以直接通過user.getUserProps()方法獲得其中子集合;而Hibernate3則不行了,缺省lazy是true,在session關(guān)閉情況下,只有兩種方式獲得子集合:

  1. Open session in view,也就是在表現(xiàn)層一直打開持久層的session,這不但違背分層不干擾原則,而且造成數(shù)據(jù)庫連接一直打開,一旦出錯,有可能造成內(nèi)存泄漏死機等問題。

  2.在load父對象User時,調(diào)用Hibernate.initialize(user.getUserProps());強行裝載所有的子對象,這樣問題是:我們再也無法通過簡單一句load生成父對象User及其所有內(nèi)部部分,而無須照顧其內(nèi)部關(guān)系。

  板橋?qū)嵺`中總結(jié)方法是:根據(jù)當(dāng)初EJB CMP的讀取模式,采取JDBC來讀取整個User及其部分子集合,缺點也是必須在Dao語句中打開User(破壞封裝),根據(jù)其內(nèi)部結(jié)構(gòu)從數(shù)據(jù)庫中獲取數(shù)據(jù),這樣的好處是:我們可以使用統(tǒng)一的Hibernate模板來進行任何一個模型的持久化(不必為每個模型寫一套DAO實現(xiàn)類),而無須關(guān)心其內(nèi)部結(jié)構(gòu)了。

  注意:Spring+Hibernate采取的是Open session in view方案,這也是這種架構(gòu)在系統(tǒng)復(fù)雜時發(fā)生性能問題一個原因,J道性能板塊有多個這樣的求救貼。

  使用Hibernate映射配置另外一個注意點就是:使用雙向關(guān)系可以提高性能,但是Evans DDD告訴我們,建模時盡量搞 單向關(guān)系,不要用雙向,這兩者有矛盾之處,實際中,我們?nèi)绻褂肏ibernate作為持久層框架,那么就采取雙向,性能很重要啊,否則后果很嚴重,這種設(shè)計和性能不匹配也是目前面向?qū)ο箢I(lǐng)域需要解決的另外一個問題。

  通過在子對象UserPropery配置中引入many-to-one ,然后在父對象User配置中規(guī)定inverse="true" 來實現(xiàn)雙向,Hibernate會通過和insert或update一條SQL語句完成關(guān)系設(shè)定。

?

?

?

表現(xiàn)層Struts聚合實現(xiàn)


  前面我們完成了Hibernate的映射配置,下面是表現(xiàn)層的映射配置,這是使用標(biāo)簽庫來實現(xiàn),我們使用Struts的標(biāo)簽庫來實現(xiàn):在界面主要實現(xiàn)下圖效果:

?


Java EE/J2EE面向?qū)ο髮崙?zhàn)之道
?


  ? 當(dāng)進行用戶User資料增刪改查時,需要一個如圖錄入頁面,部門是通過下來菜單選擇,用戶屬性UserPropery是通過一行行屬性名稱和屬性值輸入的,主要是在user.jsp中完成:


?

    
      <html:form action="/userSaveAction.do" method='post'>
<html:hidden property="action" />

<!-- 下拉菜單選擇部門,通過使用Struts的Action串聯(lián),產(chǎn)生deptListForm新ActionForm-->

<html:select property="dept.deptId" >
<logic:notEmpty name="deptListForm" >
<html:optionsCollection name="deptListForm" property="list" value="deptId" label="name"/> 
</logic:notEmpty>
</html:select>
<br>
UserId:<html:text property="userId" />
<br>
Username:<html:text property="username" />

<table>
<tr><td>屬性Id</td><td>屬性名稱</td><td>屬性值</td></tr>

<tr><td> 
<html:hidden property="userProp[0].propId" />
</td><td> 
<html:text property="userProp[0].name" />
</td><td>
<html:text property="userProp[0].value" />
</td></tr>

<tr><td>
<html:hidden property="userProp[1].propId" />
</td><td> 
<html:text property="userProp[1].name" />
</td><td>
<html:text property="userProp[1].value" />
</td></tr>

<tr><td>
<html:hidden property="userProp[2].propId" />
</td><td> 
<html:text property="userProp[2].name" />
</td><td>
<html:text property="userProp[2].value" />
</td></tr>

</table>

<br><input type='submit' value='submit'></input>
</html:form>
    
  

?

?

?? ? ?相應(yīng)的UserActionForm和User Model內(nèi)容差不多,不同之處:為接受多個動態(tài)屬性的輸入,需要設(shè)定一個特定的方法:

?

    
      public class UserForm extends ModelForm {

  .....   
  public UserProperty getUserProp(int index) {
    return (UserProperty)((List)userProps).get(index);
  }
  .....   

}
    
  

?

?

  ? 增刪改查和批量查詢根據(jù)JdonFramework的簡化可迅速配置實現(xiàn),這里不再描述,整個項目的代碼結(jié)果如下圖:也就是10個類左右,而且都是和業(yè)務(wù)有關(guān),簡要,扣主題,整個案例代碼是免費自由下載, 作為JdonFramework應(yīng)用源碼下載之一的sample


Java EE/J2EE面向?qū)ο髮崙?zhàn)之道
?


?

總結(jié)


  一個真正面向?qū)ο蟮腏avaEE或J2EE系統(tǒng),應(yīng)該是一個圍繞領(lǐng)域模型的多層架構(gòu),以面向?qū)ο驩O思維進行領(lǐng)域模型提煉和重構(gòu),繼續(xù)以O(shè)O思維進行表現(xiàn)層和持久層的配置實現(xiàn),才能尋找到一條Java系統(tǒng)快速有效高質(zhì)量的解決之道。

?

?

Java EE/J2EE面向?qū)ο髮崙?zhàn)之道


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!??!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 色黄网站成年女人色毛片 | 香蕉福利久久福利久久香蕉 | 日韩中文字幕不卡 | 神马影院午夜剧场 | 九九热最新 | 国产一毛片 | 狠狠色很很在鲁视频 | 国产精品视频第一区二区 | 天天爽天天 | 在线播放五十路乱中文 | 欧美成人午夜精品一区二区 | 日本伊人色综合网站 | 久久精品日日躁夜夜躁欧美 | 国产一区二区在线视频观看 | 中文字幕第一页亚洲 | 亚洲国产一区二区a毛片 | 色婷婷综合久久久久中文一区二区 | 亚洲美女在线视频 | 国产成人乱码一区二区三区在线 | 免费看一级欧美毛片视频 | 久久优 | 亚洲精品综合久久 | 九九精彩视频在线观看视频 | 97在线视 | 看免费5xxaaa毛片30厘米 | 欧美性色黄大片一级毛片视频 | 华人亚洲欧美精品国产 | 玖玖在线播放 | 亚洲免费福利视频 | 成人免费播放视频777777 | 成人亚洲欧美综合 | 天天射美女 | 亚洲四虎影院 | 毛片3| 午夜色影院| 干干日日 | 久久久精品久久久久久 | 国产综合亚洲欧美日韩一区二区 | 四虎影视最新网址 | 看毛片网| 五月天婷婷激情 |