隨筆-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 紫蝶∏飛揚↗ 閱讀(1127) 評論(0)  編輯  收藏 所屬分類: Hibernate數據庫
          主站蜘蛛池模板: 二手房| 泉州市| 思南县| 石首市| 巨野县| 高邮市| 永福县| 伊春市| 衡阳县| 仁怀市| 霍城县| 北川| 嘉荫县| 怀宁县| 西平县| 高州市| 奉新县| 湘乡市| 昌乐县| 江源县| 喀喇沁旗| 兴隆县| 察隅县| 九龙坡区| 绵竹市| 蒙城县| 桃源县| 扎赉特旗| 普定县| 二连浩特市| 自贡市| 定远县| 德阳市| 河曲县| 西吉县| 汾阳市| 乐陵市| 松潘县| 富源县| 万荣县| 凤城市|