隨筆 - 25  文章 - 32  trackbacks - 0
          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          常用鏈接

          留言簿(2)

          隨筆檔案

          文章分類

          文章檔案

          相冊(cè)

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜



          一個(gè)圖書管理系統(tǒng)中的兩個(gè)對(duì)象:Book(書籍),BookType(書籍類型)。Book和BookType之間是多對(duì)一關(guān)系。

          說到主從表的關(guān)聯(lián)關(guān)系,自然而然地想起的一種實(shí)現(xiàn)方式就是選擇框,比如在Book的編輯界面是使用一個(gè)類型的下拉選擇框,選擇一個(gè)類型,然后保存。于是就有下例代碼:
          <h:selectOneMenu id="type" value="#{bookHome.instance.bookType.typeId}">
                              
          <f:selectItems value="#{bookTypeList.typeSelectItems}" />
          </h:selectOneMenu>
          這段代碼的作者(我)原本的想法是讓這個(gè)下拉框與bookHome.instance里的bookType.typeId幫定。比如當(dāng)前的book類型id是1,修改后將book類型的id改為2,更新到數(shù)據(jù)庫。但是很不幸。這段代碼并不能執(zhí)行預(yù)期的行為,或者說它還附加了其他行為。即Seam已經(jīng)覺察到了在這個(gè)book中的類型的一個(gè)屬性(主鍵值)已經(jīng)改變了。于是,試圖更新這個(gè)類型。但是JPA的規(guī)范中是不允許更改主鍵的,這就引起了一個(gè)錯(cuò)誤。不信可以試下哦,呵呵。(以上描述我已經(jīng)盡可能說清楚我的想法,但可能還是不怎么清楚,希望大家看不懂的說說哪里看不懂,我好改正)。我想說的是,不要直接幫定到外鍵,而是現(xiàn)幫定到一個(gè)臨時(shí)變量,比如在bookHome中多寫一個(gè)變量:
          public class BookHome extends EntityHome<Book>{
          private Long typeId;
          //..getter setter
          }
          然后將下拉框邦定到這個(gè)變量上,比如:

          <h:selectOneMenu id="type" value="#{bookHome.typeId}">
                              
          <f:selectItems value="#{bookTypeList.typeSelectItems}" />
          </h:selectOneMenu>
          。然后在重載的persist或者update方法中寫上:
          BookType newType = getEntityManager().find(BookType.class, typeId);
          instance.setType(newType);
          return super.persist();
          就完成了。我叫它“轉(zhuǎn)移邦定”,呵呵

          Seam的解決方案:
          其實(shí)Seam有另一種解決方案。比如如果你是自動(dòng)生成代碼的方式,在BookEdit.xhtml中就會(huì)看到這樣的代碼:
          <div class="association" id="bookTypeParent">
              
                  
          <h:outputText value="There is no bookType associated with this book." 
                             rendered
          ="#{bookHome.instance.bookType == null}"/>
                  
                  
          <rich:dataTable var="bookType" 
                             value
          ="#{bookHome.instance.bookType}" 
                          rendered
          ="#{bookHome.instance.bookType != null}"
                        rowClasses
          ="rvgRowOne,rvgRowTwo"
                                id
          ="bookTypeTable">
                      
          <h:column>
                          
          <f:facet name="header">typeId</f:facet>
                          #{bookType.typeId}
                      
          </h:column>
                      
          <h:column>
                          
          <f:facet name="header">bookType typeId</f:facet>
                          #{bookType.bookType.typeId}
                      
          </h:column>
                      
          <h:column>
                          
          <f:facet name="header">typeName</f:facet>
                          #{bookType.typeName}
                      
          </h:column>
                      
          <h:column>
                          
          <f:facet name="header">action</f:facet>
                          
          <s:link view="/BookType.xhtml" 
                                   id
          ="viewbookType" 
                                value
          ="View" 
                          propagation
          ="none">
                              
          <f:param name="bookTypeTypeId" 
                                     value
          ="#{bookType.typeId}"/>
                          
          </s:link>
                      
          </h:column>
                  
          </rich:dataTable>

                  
          <div class="actionButtons">
                      
          <s:button value="Select bookType"
                                 view
          ="/BookTypeList.xhtml">
                          
          <f:param name="from" value="BookEdit"/>
                      
          </s:button>
                  
          </div>
                  
              
          </div>
          點(diǎn)擊“Select bookType”頁面就自動(dòng)跳轉(zhuǎn)到BookTypeList頁面,列出所有的類型,每個(gè)類型后面都有一個(gè)select連接,點(diǎn)擊這個(gè)連接就可選中這個(gè)類型。然后回到BookEdit.xhtml。很Seam很強(qiáng)大吧,呵呵。其實(shí)為何這樣能完成一個(gè)選擇都是在BookEdit.page.xml里配置的。配置大概如下:
             <begin-conversation join="true"/>
             
             
          <action execute="#{bookHome.wire}"/>
             
             
          <param name="bookFrom"/>
             
          <param name="bookBookId" value="#{bookHome.bookBookId}"/>
             
          <param name="bookTypeFrom"/>
             
          <param name="bookTypeTypeId" value="#{bookTypeHome.bookTypeTypeId}"/>
           <begin-conversation join="true"/>  :開始一個(gè)conversation(我暫稱之為“頁面流”),如果已存在,就加入。而不重新創(chuàng)建。
          <action execute="#{bookHome.wire}"/>  :一最重要的這個(gè)。如果沒有執(zhí)行這個(gè)方法這段跳轉(zhuǎn)就沒有任何效果了。,先來看下這個(gè)方法是怎么寫的吧:

          public void wire() {
                  getInstance();
          //獲取instance,放在這里是為了加在instance
                  BookType bookType = bookTypeHome.getDefinedInstance();//獲取類型。
                  if (bookType != null) {//如果選擇的類型不為null
                      getInstance().setBookType(bookType);//設(shè)置書籍類型
                  }
              }

          那bookTypeHome從哪來的呢?天上掉下的?呵呵,當(dāng)然不是。就在BookHome的上部分:
          @In(create = true)
              BookTypeHome bookTypeHome;

          前面我說過了。這個(gè)@In就是拿來做雙向注入的。bookTypeHome是要注入的組件名稱。
          其他的都是參數(shù)了,沒啥好解釋的。
          但為什么在BookTypeList頁面點(diǎn)select,怎么就會(huì)自動(dòng)跳轉(zhuǎn)到BookEdit.xhtml呢?奧秘就在這段代碼里(BookTypeList.xhtml):
          <s:link view="/#{empty from ? 'BookType' : from}.xhtml" 
                             value
          ="Select" 
                                id
          ="bookType">
                          
          <f:param name="bookTypeTypeId" 
                                  value
          ="#{bookType.typeId}"/>
                      
          </s:link>
          從BookEdit里傳來一個(gè)from。
          <s:button value="Select bookType"
                                 view
          ="/BookTypeList.xhtml">
                          
          <f:param name="from" value="BookEdit"/>
                      
          </s:button>
          就告訴了BookTypeList,是從BookEdit里來的,點(diǎn)Select的時(shí)候就不要去其他地方了。直接回去。

          好了,今天到這,困了,上面講的不明白的歡迎email或qq聯(lián)系我。。


          posted on 2008-12-24 23:02 phyeas 閱讀(1079) 評(píng)論(4)  編輯  收藏 所屬分類: Seam項(xiàng)目實(shí)戰(zhàn)

          FeedBack:
          # re: Seam新手實(shí)戰(zhàn)(4):外鍵 2009-01-19 16:21 藍(lán)天飛翔
          不要那么懶啊~~你多寫一些,我們就多學(xué)一些。呵呵
          在此謝謝謝了···  回復(fù)  更多評(píng)論
            
          # re: Seam新手實(shí)戰(zhàn)(4):外鍵 2009-01-31 09:06 phyeas
          @藍(lán)天飛翔
          呵呵,最近事情比較多。。  回復(fù)  更多評(píng)論
            
          # re: Seam新手實(shí)戰(zhàn)(4):外鍵 2009-02-25 10:51 藍(lán)天飛翔
          第一次看時(shí),好多不明白,今天我又回來仔細(xì)看了看,解決好多的凝問,再次感謝!希望有空多寫寫。  回復(fù)  更多評(píng)論
            
          # re: Seam新手實(shí)戰(zhàn)(4):外鍵[未登錄] 2011-07-02 11:58 s
          我是看著這長(zhǎng)大的  回復(fù)  更多評(píng)論
            
          主站蜘蛛池模板: 博罗县| 连平县| 海宁市| 桦川县| 德江县| 长葛市| 商城县| 翁牛特旗| 咸阳市| 东兴市| 当雄县| 明溪县| 双牌县| 庆城县| 健康| 张家川| 常德市| 九龙城区| 广宗县| 岢岚县| 上林县| 措勤县| 红原县| 曲麻莱县| 建始县| 贞丰县| 南部县| 达州市| 阆中市| 义乌市| 马关县| 什邡市| 黄平县| 柳林县| 苍南县| 盐边县| 永清县| 万宁市| 申扎县| 彭阳县| 沙河市|