posts - 14,  comments - 37,  trackbacks - 0
          CallBack在EJb3 spec中不過是一小章節(jié),似乎不是很引人注意,剛開始,也沒有引起我們的多少注意, 然而,在開發(fā)中,當我們實際運用它來解決問題的時候,發(fā)現(xiàn)它的實際作用還是很大的。 其實,從根本來說,CallBack相當于ORM Engine和用戶設計的Domain Model(可持久話的模型) 之間一道天然的鉤子,通過它,設計者可以放入很多類似橫切面的關注點。 下面給出一個真實的例子:
          銀行需要對涉及帳務每一個操作實行錄入,復核機制。假設操作涉及實體有Customer,Account。 錄入紀錄實體為InputRecord, 復核紀錄為:ConfirmRecord.用戶為User。
          初步設計時,這些類的骨干代碼為:
                  @Entity
          class User{
          @Id
          long id=-1;
          String userName;
          String passwordHex;
          }
          @Entity
          class Customer{
          @Id
          long id=-1;
          String name;
          @OneToOne
          InputRecord inputRecord;
          @OneToOne
          ConfirmRecord confirmRecord;
          }
          @Entity
          class Account{
          @Id
          long id=-1;
          String accountName;
          String accountNo;
          @OneToOne
          InputRecord inputRecord;
          @OneToOne
          ConfirmRecord confirmRecord;
          }
          //Not a persistence Entity
          abstract class OperationRecord{
          @Id
          long id=-1;
          @ManyToOne
          User user;
          Date date;
          }
          @Entity
          class InputRecord extends OperationRecord{
          //nothing ,just define a concrete class and table
          }
          @Entity
          class ConfirmRecord extends OperationRecord{
          //nothing ,just define a concrete class and table
          }
          
          上面這段代碼有幾點需要說明一下:
          1) OperationRecord沒有聲明為Entity,這里沒有用到繼承策略,因為對象繼承與數(shù)據(jù)庫之間的映射并不是很好,在一般設計中,我是很少使用它的,繼承和數(shù)據(jù)共享兩者是沒有什么關聯(lián)的, 因為在內存中,他們的實例始終是互補相干的數(shù)據(jù)副本,單純從數(shù)據(jù)來說,分別對應到不同的表中來存儲就是最好的映射,而行為的繼承在JVM中可以得到完全的體現(xiàn)。基于這個認識,InputRecord,ConfirmRecord僅僅起表明類型的作用。
          2)從Account,Customer的代碼中可以看出InputRecord,ConfirmRecord域是重復出現(xiàn)的,而且從需求來看,會有更多的實體需要這兩個Field,從1)的分析中,很自然而然的抽取一個基類出來:

              abstract class ConfirmableEntity{
          @OneToOne
          InputRecord inputRecord;
          @OneToOne
          ConfirmRecord confirmRecord;
          }
          class Customer extends ConfirmableEntity{
          }
          


          到這里,一個對需求的思考同時也出現(xiàn)了,在什么地方紀錄操作記錄呢? AOP? TemplateMethod? 很多種可選的方案。然而,從代碼量和簡潔性來說,CallBack是好的。采用CallBack的基本骨干代碼如下:

              abstract class ConfirmableEntity{
          @PostPersist
          public void registerInputRecord(){
          //retrieve current user
          User currentUser = UserHolder.getCurrentUser();
          //create an inputRecord for current User
          InputRecord inputRec = new InputRecord(currentUser);
          setInputRecord(inputRec);
          }
          }
          

          所有的需要錄入復核得實體只要繼承自這個ConfirmableEntity,不僅獲得數(shù)據(jù),同樣獲得了相應的行為。這么一段代碼對于他們來說基本上時透明的。(有點類似AOP? )上面的代碼中,UserHolder是一個非常有意思的設計,用戶的保持一般有不同的需求,在Web中有Session,而在別的應用中就不一定使用這樣的機制了,但不管如何,我們總歸有在領域層提出獲取當前操作用戶的需求,一個很簡單的設計會讓很多事情變得簡單,可以把UserHolder當作一個隔離領域層和具體App層用戶管理的接口,大家如果對它得出現(xiàn)比較有詫異的話可以再具體討論一下.

          值得一說的是,這樣的設計對于以后的可擴展也帶來了巨大的影響,比如,用戶提出需求:對于已經復核得操作紀錄不能再被修改,刪除。那么我們只要再在ConfirmableEntity上寫一個CallBack即可:
              abstract class ConfirmableEntity{
          @PostPersist
          public void registerInputRecord(){
          //retrieve current user
          User currentUser = UserHolder.getCurrentUser();
          //create an inputRecord for current User
          InputRecord inputRec = new InputRecord(currentUser);
          setInputRecord(inputRec);
          }
          @PreUpdate
          @PreRemove
          public void check(){
          if(getConfirmRecord()!=null && getConfirmRecord().getId()>0 )
          throw new SecurityException("can not update/remove confirmed record");
          }
          }
          
          posted on 2007-07-30 11:20 冰封的愛 閱讀(361) 評論(0)  編輯  收藏 所屬分類: J2EE
          <2025年7月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          常用鏈接

          留言簿(3)

          隨筆檔案

          文章分類

          文章檔案

          相冊

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 西城区| 如东县| 武强县| 通化市| 门源| 揭东县| 朝阳县| 蓬溪县| 木里| 曲阳县| 桓台县| 石阡县| 若尔盖县| 凤山市| 达孜县| 始兴县| 兴国县| 花垣县| 大余县| 突泉县| 乃东县| 吴川市| 海城市| 吉隆县| 德兴市| 神木县| 永春县| 阜新| 桐乡市| 且末县| 赣榆县| 海丰县| 徐水县| 通山县| 龙里县| 清水县| 上栗县| 大余县| 新蔡县| 湘潭县| 腾冲县|