熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java開源技術 >> 正文

Hibernate中any元素的應用體會

2013-11-23 20:08:47  來源: Java開源技術 

  Hibernate中any元素的應用體會
  
  關聯(Associations)是Hibernate核心概念之一比較常用的有
  
  manytoone onetoone onetomany manytomany
  
  Hibernate還提供了另外一種關聯——異類關聯(Heterogeneous Associations)
  
  在Hibernate Reference (cn) 中是這樣說明的
  
  引用:
  
   異類關聯(Heterogeneous Associations)
  
  <manytoany>和<indexmanytoany>元素提供真正的異類關聯這些元素和<any>元素工作方式是同樣的他們都應該很少用到
  
  下面針對<any>元素談一些自己的體會
  
  什麼時候需要<any>元素
  
  持久類中一個屬性關聯另外一個指定的持久類(幾乎每個應用都有這種情況)多半會使用manytoone onetoone這樣的關聯映射到關系數據庫中也多半使用外鍵約束
  
  可能會遇到有這麼一種特殊的情況需要持久類中一個屬性關聯另外一些持久類
  
  舉個例子Log類中使用logEntity屬性關聯一組業務持久類(也就是說在Log中記錄不同業務類的實例對象)
  
  如果使用manytoone則有很大的限制首先需要這些業務類都要繼承一個超類而且在數據庫中必須有這個超類對應的表在Hibernate提供的三種繼承映射策略中只能使用前兩種
  
  每棵類繼承樹使用一個表(table per class hierarchy)
  
  每個子類一個表(table per subclass)
  
  第種通常不大合適所有的業務類映射為一張表冗余過多限制也多增加一個業務類就需要修改表結構不易擴展
  
  第種的情況是表的數量=業務表數量 + 一個超類表子類表通過主鍵和超類表關聯(所以實際上關系模型是一對一關聯)業務表數量比較多的時候這種結構的性能和靈活性都有問題
  
  這時<any>元素就派上用場啦
  
  <any>元素的應用
  
  
  
  業務類
  java代碼:
  
  public class BizOne {
  private Long    id;
  private String    bizOneDescription;
  //Getters and Setters 省略
  }
  public class BizTwo {
  private Long    id;
  private String    bizTwoDescription;
  private Date  createDate;
  //Getters and Setters 省略
  }
  
  日志類
  java代碼:
  
  public class MyLog {
  private Long    id;
  private Date    logDate;
  private Object    logEntity;    //這就是<any>元素對應的屬性
  //Getters and Setter 省略
  }
  
  hbmxml 和 表結構
  
  這裡只給出MyLog的hbmxml(BizOne BizTwo很簡單不提了)
  
  java代碼:
  
  <hibernatemapping>
  <class name=comtestentityMyLog table=MyLog>
  <id name=id column=id>
  <generator class=native/>
  </id>
  <property name=logDate/>
  <any name=logEntity metatype=string idtype=long>
  <metavalue value=One class=comtestentityBizOne/>
  <metavalue value=Two class=comtestentityBizTwo/>
  <column name=entityMetaValue length= />
  <column name=entityId/>
  </any>
  </class>
  </hibernatemapping>
  
  表結構(MySQL)
  java代碼:
  
  create table MyLog (
  id BIGINT NOT NULL AUTO_INCREMENT
  logDate datetime
  entityMetaValue VARCHAR()
  entityId BIGINT
  primary key (id)
  )
  
  對<any>元素中子元素和屬性的理解可以結合生成的表結構及其表中的數據(見
  
  name: 是持久類中屬性名稱
  metatype: 是下面metavalue元素中value的類型stringcharacter
  idtype: 是引用類的主鍵類型
  metavalue元素中value: 該值將保存到數據庫表中用來標識其後的class即引用的持久類請參考下面的數據
  metavalue元素中class: 引用持久類的類全稱
  
  第一個column: 保存上面value值的字段
  
  第二個column: 保存引用持久類的主鍵值的字段它的類型是idtype對應到數據庫中的字段類型
  
  記錄日志的方法
  
  java代碼:
  
  public MyLog recordLog(Object biz){
  MyLog log = new MyLog();
  logsetLogDate(new Date());
  logsetLogEntity(biz);    //引用了傳遞過來的業務對象
  
  return getLogService()save(log);    //保存log我習慣用Spring+Hibernate
  }
  
  Hibernate所保存的數據是這樣
  
  引用:
  
         
  id  logDate           entityMetaValue entityId
         
     ::  One        
     ::  Two        
     ::  One        
     ::  Two        
     ::  Two        
  
  讀取Log
  java代碼:
  
  public MyLog readLog(Long id){
  MyLog log = getLogService()getLog(id);
  
  Object biz = loggetLogEntity();
  //
  
  return log;
  }
  
  用<any>所實現的關聯與<manytoone>等關聯的效果是相同的例如如果BizOne BizTwo的lazy=true則biz是個代理
  
  BizThree如果增加了一個業務類BizThree在MyLoghbmxml中只需增加一行
  
  java代碼:
  
  <metavalue value=Three class=comtestentityBizThree/>
  
  限制
  
  在<any>元素中需要指定idtype這可能是<any>對所關聯類的唯一限制了所關聯的類的主鍵類型必須相同
  
  再談繼承映射策略問題
  
  上面提到了如果為了讓Log能夠關聯業務類就要求業務類都要繼承同一個超類是不大合適的不過不合適的理由在於這個超類需要在數據庫有相應的表不能說業務類不能繼承一個超類實際上很多應用中的業務類都有超類而且根據情況實現一些接口此時的繼承映射策略是Hibernate Reference中的第三種每個具體類一個表(table per concrete class)上面MyLog中的logEntity的類型可以是更有意義的超類如Entity當然也可以是接口不必是Object這樣即使超類在數據庫中沒有對應的表照樣可以實現關聯
  
  彩票
  
  Hibernate Reference中提到<any>元素的地方不是很多但提到時總不忘記說應該很少用到應該在非常特殊的情況下使用它可能從全世界的角度看使用<any>是低概率事件但是如果遇到了就是%的概率了因此當你應用<any>的時候別忘了購買彩票因為與中獎同樣的低概率事件——使用<any>——你已經碰到了你的運氣就來了趕快買彩票吧准能中獎!
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28015.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.