隨筆-9  評論-168  文章-266  trackbacks-0
Hibernate Annotation幾種關聯映射
一對一(One-To-One)
使用@OneToOne注解建立實體Bean之間的一對一關聯。一對一關聯有三種情況:(1).關聯的實體都共享同樣的主鍵,(2).其中一個實體通過外鍵關聯到另一個實體的主鍵(注意要模擬一對一關聯必須在外鍵列上添加唯一約束),(3).通過關聯表來保存兩個實體之間的連接關系(要模擬一對一關聯必須在每一個外鍵上添加唯一約束)。
 
1.共享主鍵的一對一關聯映射:
@Entity
@Table(name="Test_Body")
public class Body {
   private Integer id;
   private Heart heart;
   @Id
   public Integer getId() {
      return id;
   }
   public void setId(Integer id) {
      this.id = id;
   }
   @OneToOne
   @PrimaryKeyJoinColumn
   public Heart getHeart() {
      return heart;
   }
   public void setHeart(Heart heart) {
      this.heart = heart;
   }
}
@Entity
@Table(name="Test_Heart")
public class Heart {
   private Integer id;
   @Id
   public Integer getId() {
      return id;
   }
   public void setId(Integer id) {
      this.id = id;
   }
}
通過@PrimaryKeyJoinColumn批注定義了一對一關聯
 
2.使用外鍵進行實體一對一關聯:
@Entity
@Table(name="Test_Trousers")
public class Trousers {
   @Id
   public Integer id;
   @OneToOne
   @JoinColumn(name = "zip_id")
   public TrousersZip zip;
}
@Entity
@Table(name="Test_TrousersZip")
public class TrousersZip {
   @Id
   public Integer id;
   @OneToOne(mappedBy = "zip")
   public Trousers trousers;
}
上面的例子是指Trousers通過Trousers的外鍵列zip_id和TrousersZip關聯,@JoinColumn批注定義了聯接列,該批注和@Column批注有點類似,但是多了一個名為referencedColumnName的參數。該參數定義了所關聯目標實體中的聯接列,注意,當referencedColumnName關聯到非主鍵列的時候,關聯的目標類必須實現Serializable,還要注意的是所映像的屬性對應單個列(否則映射無效)
一對一關聯可能是雙向的,在雙向關聯中,有且僅有一端作為主體(owner)端存在:主體端負責維護聯接列(即更新),對于不需要維護這種關系的從表則通過mappedNy屬性進行聲明。mappedBy的值指向主體的關聯屬性。例子中,mappedBy的值為zip。最后,不必也不能再在被關聯端(ownedside)定義聯接列了,因為已經在主體端聲明了。
如果在主體沒有聲明@JoinColumn,系統自動進行處理:在主表(owner table)中將創建聯接列,列名為:主體的關聯屬性名+下劃線+被關聯端的主鍵列名。上面的例子中是zip_id,因為Trousers中的關聯屬性名為zip,TrousersZip的主鍵是id。
 
3.通過關聯表定義一對一關聯
@Entity
@Table(name="Test_People")
public class People {
   @Id
   public Integer id;
   @OneToOne
   @JoinTable(name ="TestPeoplePassports",
      joinColumns =@JoinColumn(name="people_fk"),
      inverseJoinColumns =@JoinColumn(name="passport_fk")
   )
   public Passport passport;
}
@Entity
@Table(name="Test_Passport")
public class Passport {
   @Id
   public Integer id;
   @OneToOne(mappedBy = "passport")
   public People people;
}
People通過名為TestPeoplePassports的關聯表和Passport關聯。該關聯表擁有名為passport_fk的外鍵列,該外鍵指向Passport表,該信息定義為inverseJoinColoumns的屬性值,而people_fk外鍵列指向People表,該信息定義為joinColumns的屬性值。
這種關聯可能是雙向的,在雙向關聯中,有且僅有一端作為主體(owner)端存在:主體端負責維護聯接列(即更新),對于不需要維護這種關系的從表則通過mappedNy屬性進行聲明。mappedBy的值指向主體的關聯屬性。例子中,mappedBy的值為passport。最后,不必也不能再在被關聯端(ownedside)定義聯接列了,因為已經在主體端聲明了。
以上是一對一關聯的三種形式,下面介紹多對一關聯。
 
 
 
多對一(Many-to-One)
使用@ManyToOne批注來實現多對一關聯。
@ManyToOne批注有一個名為targetEntity的參數,該參數定義了目標實體名,通常不需要定義該參數,因為在大部分情況下默認值(表示關聯關系的屬性類型)就可以很好的滿足需求了。不過下面這種情況下這個參數就顯得有意義了:使用接口作為返回值而不是常見的實體。
@ManyToOne(targetEntity=CompanyImpl.class)
@JoinColoumn(name=”COPM_ID”)
Public Company getCompany(){
   return company;
}
多對一的配置方式有兩種:(1)通過@JoinColoumn映像(2)通過關聯表的方式來映像
 
(1)           通過@JoinColoumn映射
SRD Framework中Company,Category例子:
Company:
@ManyToOne
   @JoinColumn(name = "CATEGORY_OPTION_ID")
   private Category category = null;
   Category:
@DiscriminatorValue("Category")
public class Category extends Option {
}
(2)           通過關聯表映射
通過@JoinTable批注定義關聯表,該關聯表包含了指回實體表的外鍵(通過@JoinTable.joinColoumns)以及指向目標實體表的外鍵(通過@JoinTable.inverseJoinColoumns)
@Entity
@Table(name="Test_TreeType")
public class TreeType {
   private Integer id;
   private String name;
   private ForestType forestType;
   @ManyToOne(fetch = FetchType.LAZY)
   @JoinTable(name="Test_Tree_Forest",
      joinColumns = @JoinColumn(name="tree_id"),
      inverseJoinColumns = @JoinColumn(name="forest_id") )
public ForestType getForestType() {// forestType的getter,setter方法必須在這里,否則會出錯
      return forestType;
   }
   public void setForestType(ForestType forestType) {
      this.forestType = forestType;
   }
   @Id
   @GeneratedValue
   public Integer getId() {
      return id;
   }
   public void setId(Integer id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
}
@Entity
@Table(name="Test_ForestType")
public class ForestType {
   private Integer id;
   private String name;
   private Set<TreeType> trees;
   @OneToMany(mappedBy="forestType")
public Set<TreeType> getTrees() {// trees的getter,setter方法必須在這里,否則會出錯
      return trees;
   }
   public void setTrees(Set<TreeType> trees) {
      this.trees = trees;
   }
   @Id @GeneratedValue
   public Integer getId() {
      return id;
   }
   public void setId(Integer id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
}
 
一對多(One-to-Many)
使用@OneToMany批注可定義一對多關聯,一對多關聯可以是雙向關聯。
在EJB3規范中多對一這端幾乎總是雙向關聯中的主體(owner)端,而一對多這端關聯批注為@OneToMany(mappedBy...)
@Entity
Public class Troop{
   @OneToMany(mappedBy=”troop”)
Public Set<Soldier> getSoldiers(){
......
}
@Entity
Public class Soldier{
   @ManyToOne
   @JoinColumn(name=”troop_fk”)
Public Troop getTroop(){
......
}
Troop通過troop屬性和Soldier建立一對多的雙向關聯,在mappedBy端不必也不能再定義任何物理映射。
對于一對多的雙向映射,如果要一對多這一端維護關聯關系,你需要刪除mappedBy元素并將多對一這端的@JoinColoumn的insertable和updatabel設置為false。這種方案不會得到什么明顯的優化,而且還會增加一些附加的UPDATE語句。
 
單向:
通過在被擁有的實體端(owned entity)增加一個外鍵列來實現一對多單向關聯是很少見的,也是不推薦的,建議通過一個聯接表來實現這種關聯(下面會講到)。
@JoinColoumn批注來描述這種單向關聯關系
@Entity
Public class Customer{
   @OneToMany
@JoinColoumn(name=”CUST_ID”)
Public Set<ticket> getTickets() {
......
}
@Entity
Public class Ticket{
   ...
}
Customer通過CUST_ID列和Ticket建立了單向關聯關系
通過關聯表處理單向關聯:
通過聯接表處理單向一對多關聯是首選方式,這種關聯通過@JoinTable批注進行描述
@Entity
Public class Trainer{
@OneToMany
@JoinTable(
   name = "TrainedMonkeys",
   jonColumns = {@JoinColumn(name = "trainer_id")},
   inverseJoinColumns = @JoinColumn(name = "monkey_id")
   )
public Set<Monkey> getTrainedMonkeys() {
      return trainedMonkeys;
   }
......
}
@Entity
public class Monkey {
...//no bidir
}
上面這個例子中,Trainer通過TrainedMonkeys表和Monkey建立了單向關聯,其中外鍵trainer_id關聯到Trainer(joinColoumn),而外鍵monkey_id關聯到Monkey(inversejionColoumns)
默認處理機制:
通過聯接表來建立單向一對多關聯不需要描述任何物理映像,表名由以下三個部分組成:主表(ownertable)表名+從表(the other side table)表名,指向主表的外鍵名:主表表名+下劃線+主表主鍵列名,指向從表的外鍵名:主表所對應實體的屬性名+下劃線+從表主鍵列名,指向從表的外鍵定義為唯一約束,用來表示一對多的關聯關系。
@Entity
public class Trainer{
   @OneToMany
   Public Set<Tiger> getTrainedTigers(){
... ...
}
@Entity
public class Tiger{
.. ..//no bidir
}
上面這個例子中,Trainer和Tiger通過聯接表Trainer_Tiger建立單向關聯關系,其中外鍵trainer_id關聯到Trainer,而外鍵trainedTigers_id關聯到Tiger
 
多對多(Many-to-Many)
使用@ManyToMany批注可定義多對多關聯,同時,你也許要通過批注@JoinTable描述關聯表和關聯條件。如果是雙向關聯,其中一段必須定義為Owner,另一端必須定義為inverse(在對關聯表進行更新操作時這一端將被忽略)
@Entity()
public class Employer implements Serializable {
   private Integer id;
   private Collection employees;
   @ManyToMany(
targetEntity = org.hibernate.test.annotations.manytomany.Employee.class,
      cascade = {CascadeType.PERSIST, CascadeType.MERGE}
   )
   @JoinTable(
         name = "EMPLOYER_EMPLOYEE",
         joinColumns = {@JoinColumn(name = "EMPER_ID")},
         inverseJoinColumns = {@JoinColumn(name = "EMPEE_ID")}
   )
   public Collection getEmployees() {
      return employees;
   }
...
}
@Entity()
public class Employee implements Serializable {
   @ManyToMany(
         cascade = {CascadeType.PERSIST, CascadeType.MERGE},
         mappedBy = "employees"
         targetEntity = Employer.class
   )
public Collection<Employer> getEmployers() {
      return employers;
   }
.. ..
}
@JoinTable批注定義了聯接表的表名,聯接列數組,以及invers聯接列數組,后者是關聯表中關聯到Employee主鍵的列(the “other side”)。
被關聯端不必也不能描述物理映射:只需要一個簡單的mappedBy參數,該參數包含了主體端的屬性名,這樣就綁定了雙方的關系。
默認值:
和其它許多批注一樣,在多對多關聯中很多值是自動生成,黨雙向多對多關聯中沒有定義任何物理映射時,Hibernate根據以下規則生成相應的值,關聯表名:主表表名+下劃線+從表表名,關聯到主表的外鍵名:主表名+下劃線+主表中的主鍵列名,關聯到從表的外鍵名:主表中用于關聯的屬性名+下劃線+從表的主鍵列名,以上規則對于雙向一對多關聯同樣一樣。
 
以上是整理的一點簡單的幾種映射,可參考EJB3.pdf中P111——P131,hibernate_annotation.pdf 第二章
在這里沒有具體的例子,有很多內容還需要仔細查看文檔。
posted on 2011-12-20 14:10 紫蝶∏飛揚↗ 閱讀(932) 評論(0)  編輯  收藏 所屬分類: Hibernate 、數據庫
{ganrao} 好彩1晚上几点开奖 陕西十一选五最大遗漏 快乐10分玩法技巧 河北排列7开奖结果查询 体育彩票广西11选5 四川快乐12手机走势图 棋牌游戏软件开发制作 福建快3开今日开奖号码表 浙江福彩快乐12中奖助手 000247股票行情 江西11选五走势图爱彩乐 乐彩网排列五免费预测 今日股票市场 安徽快3开奖走势图 一定牛 福建31选7附加走势图 江苏11选5分布走势图