zoukankan      html  css  js  c++  java
  • web进修之—Hibernate 关系映射(3)

    概述

    Hibernate的关系映射是Hibernate使用的难点或者是重点(别担心,不考试哦~),按照不同的分类方式可以对这些映射关系做一个分类,如:

    按对象对应关系分:

    • 一对一
    • 多对一/一对多
    • 多对多

    按对象对应关系的方向分:

    • 单向
    • 双向

    按是否使用连接表分(当然了像多对多是必须使用连接表的):

    • 使用连接表
    • 不使用连接表

    在使用Hibernate中常常不会分得这么仔细,常常是集中分类方式糅合起来使用,但是这个分类可以帮助我们理解Hibernate中的映射关系。

    在进行详细的介绍之前,首先需要明确几个点:

    • Hibernate纷繁复杂的映射关系只是一种面向对象的思维方式,在数据库中就是体现在外键上关联上,所以理解了数据库中的外键关联,再回过头来看映射关系就柳暗花明了;
    • index在数据库中的作用:为了提高查询该列的效率;
    • constrain的作用:对该列的值进行约束(废话。。。),各个取值的含义如下
    • MUL:该列的值可以重复

    • <li><font face="宋体"><font size="3">UNI:该列不能有重复的值</font> </font></li>
      
      <li><font face="宋体"><font size="3">FK:外键,一般定义的时候会有参考哪一个表的哪一个字段</font> </font></li>
      

    代码

    废话少说,是时候展现真正的代码啦

    先看两个类Person,Address(你没看错,这是官方用来举例子的两个类)

    1. public class Address {   
    2.     private long id;   
    3.     private Set<Person> people;   
    4.     private Person person;   
    5.   
    6.     // setter,getter   
    7. }   
    8. public class Person {   
    9.     private long id;   
    10.     private Address address;   
    11.     private Set<Address> addressList;   
    12.   
    13.     // setter,getter   
    14. }  

    各种映射关系的配置文件person.hbm.xml,里面包括单向关联的配置(在靠前面),包含双向关联的配置(紧随单向之后)

    1. <!DOCTYPE hibernate-mapping PUBLIC   
    2.         "-//Hibernate/Hibernate Mapping DTD 3.0//EN"   
    3.         "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">  
    4.   
    5. <hibernate-mapping package="org.lep.hibernate.model" >  
    6.   
    7.     <class name="Person" table="person">  
    8.         <id name="id" column="person_id">  
    9.             <generator class="increment">  
    10.             </generator>  
    11.         </id>  
    12.         <!--单向关联 start-->  
    13.         <!--多对一是一对多的反向关联,一对多、多对一就构成了多对多-->  
    14.   
    15.         <!--多对一,只需要在many的一方使用many-to-one进行映射即可,和其他id、property一样name表示model里面的属性名称-->  
    16.         <!--<many-to-one name="address" column="address_id" not-null="true" />-->  
    17.   
    18.         <!--一对一,基于外键,把many-to-one的unique设置为true之后就是单向一对一,在数据库中的体现就是这个外键的值是唯一(key=UNI,如果没有设置unique的话key=mul)的,那也就是只能对应一个Address-->  
    19.         <!--有not-null约束的时候注意save对象的顺序,如果没有不用注意顺序hibernate会在保存了关联的对象之后,update到当前对象对应的表-->  
    20.         <!--<many-to-one name="address" column="address_id" not-null="true" unique="true" />-->  
    21.   
    22.   
    23.         <!--一对一,基于主键,将主键作为外键的时候,关联的对象和本对象的save顺序是有关系的,要先savereference的对象,然后在保存本对象-->  
    24.         <!-- constrained说明主键上存在一个约束,即外键,参考address-->  
    25.         <!--<id name="id" column="person_id">-->  
    26.             <!--<generator class="foreign">-->  
    27.                 <!--<param name="property">address</param>-->  
    28.             <!--</generator>-->  
    29.         <!--</id>-->  
    30.         <!--<one-to-one name="address" constrained="true" />-->  
    31.   
    32.         <!--一对多-->  
    33.         <set name="addressList">  
    34.             <key column="person_id" >  
    35.             </key>  
    36.             <one-to-many class="Address"></one-to-many>  
    37.         </set>  
    38.   
    39.         <!--单向关联 end-->  
    40.   
    41.         <!--单向关联——基于连接表 start-->  
    42.         <!--使用多对多和join的时候会产生中间表-->  
    43.         <!--一对多使用many-to-many会产生一张中间表-->  
    44.         <!--<set name="addressList" table="per_addr">-->  
    45.             <!--<key column="person_id"></key>-->  
    46.             <!--<many-to-many column="address_id" class="Address" unique="true" />-->  
    47.         <!--</set>-->  
    48.   
    49.         <!--多对一-->  
    50.         <!--<join table="per_addr" optional="true">-->  
    51.             <!--<key column="peron_id"></key>-->  
    52.             <!--<many-to-one name="address" column="address_id" not-null="true"></many-to-one>-->  
    53.         <!--</join>-->  
    54.   
    55.         <!--一对一-->  
    56.         <!--<join table="per_addr" optional="true">-->  
    57.             <!--<key column="person_id"></key>-->  
    58.             <!--<many-to-one name="address" column="address_id" not-null="true" unique="true" />-->  
    59.         <!--</join>-->  
    60.   
    61.         <!--多对多-->  
    62.         <!--<set name="addressList" table="per_addr">-->  
    63.             <!--<key column="person_id"></key>-->  
    64.             <!--<many-to-many column="address_id" class="Address"></many-to-many>-->  
    65.         <!--</set>-->  
    66.         <!--单向关联——基于连接表 end-->  
    67.   
    68.         <!--双向关联 start-->  
    69.   
    70.         <!--多对一/一对多-->  
    71.         <!--<many-to-one name="address" column="address_id" not-null="true" />-->  
    72.   
    73.         <!--一对一,基于外键关联-->  
    74.         <!--<many-to-one name="address" column="address_id" unique="true" not-null="true" />-->  
    75.   
    76.         <!--一对一,基于主键关联-->  
    77.         <!--<one-to-one name="address" />-->  
    78.   
    79.         <!--双向关联 end-->  
    80.   
    81.         <!--双向关联,使用连接表 start-->  
    82.   
    83.         <!--多对一/一对多-->  
    84.         <!--<set name="addressList" table="per_addr">-->  
    85.             <!--<key column="person_id"></key>-->  
    86.             <!--<many-to-many class="Address" column="address_id" unique="true" />-->  
    87.         <!--</set>-->  
    88.   
    89.         <!--一对一,必须指定column-->  
    90.         <!--<join table="per_addr" optional="true">-->  
    91.             <!--<key column="person_id" unique="true"></key>-->  
    92.             <!--<many-to-one name="address" column="address_id" class="Address" unique="true" />-->  
    93.         <!--</join>-->  
    94.   
    95.         <!--多对多-->  
    96.         <!--<set name="addressList" table="per_addr">-->  
    97.         <!--<key column="person_id"></key>-->  
    98.         <!--<many-to-many column="address_id" class="Address"></many-to-many>-->  
    99.         <!--</set>-->  
    100.   
    101.         <!--双向关联,使用连接表 end-->  
    102.     </class>  
    103. </hibernate-mapping>  

    address.hbm.xml(只有双向关联的配置)

    1. <!DOCTYPE hibernate-mapping PUBLIC   
    2.         "-//Hibernate/Hibernate Mapping DTD 3.0//EN"   
    3.         "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">  
    4.   
    5. <hibernate-mapping package="org.lep.hibernate.model" >  
    6.     <class name="Address" table="address">  
    7.         <id name="id" column="address_id">  
    8.             <generator class="increment"/>  
    9.         </id>  
    10.   
    11.         <!--双向关联 start-->  
    12.   
    13.         <!--多对一/一对多-->  
    14.         <!--<set name="people" inverse="true">-->  
    15.             <!--<key column="address_id"></key>-->  
    16.             <!--<one-to-many class="Person" />-->  
    17.         <!--</set>-->  
    18.   
    19.         <!--一对一,基于外键关联-->  
    20.         <!--<one-to-one name="person" constrained="true"/>-->  
    21.   
    22.         <!--一对一,基于主键关联-->  
    23.         <!--<id name="id" column="person_id">-->  
    24.             <!--<generator class="foreign">-->  
    25.                 <!--<param name="property">person</param>-->  
    26.             <!--</generator>-->  
    27.         <!--</id>-->  
    28.         <!--<one-to-one name="person" constrained="true"/>-->  
    29.   
    30.         <!--双向关联 end-->  
    31.   
    32.         <!--双向关联,使用连接表 start-->  
    33.   
    34.         <!--多对一/一对多-->  
    35.         <!--<join table="per_addr" inverse="true" optional="true">-->  
    36.             <!--<key column="address_id"></key>-->  
    37.             <!--<many-to-one name="person" column="person_id" not-null="true"></many-to-one>-->  
    38.         <!--</join>-->  
    39.   
    40.         <!--一对一,必须指定column-->  
    41.         <!--<join table="per_addr" inverse="true" optional="true">-->  
    42.             <!--<key column="address_id" unique="true"></key>-->  
    43.             <!--<many-to-one name="person" column="person_id" unique="true"  />-->  
    44.         <!--</join>-->  
    45.   
    46.         <!--多对多-->  
    47.         <!--<set name="people" inverse="true" table="per_addr">-->  
    48.         <!--<key column="address_id"></key>-->  
    49.         <!--<many-to-many column="person_id" class="Person"></many-to-many>-->  
    50.         <!--</set>-->  
    51.   
    52.         <!--双向关联,使用连接表 end-->  
    53.   
    54.     </class>  
    55. </hibernate-mapping>  

    试验过这些配置之后,我们可以总结出:

    • 一对一可以通过主键关联,也可以使用外键关联
    • 通过使用unique属性可以将多(many)的关系变为一(one)的关系,比如一对一,可以使用many-to-one unique=”true”
    • 在使用many-to-many或者使用join的时候才会产生连接表(中间表),可以根据实际情况来决定是否采用产生中间表的配置(比如查询的性能,业务逻辑的需要)
    • 如果是双向关系,在一边配置之后,另一边使用inverse=”true”来告诉Hibernate有谁来控制
    • 推荐外键设置not null,这样设置后就要注意保存对象的顺序了,比如person对address单向关联(Person有一个属性Address),那么person表里面就会有一个address_id的外键,如果这个外键设为not null,那么save的时候应该先save address,再save person
    1. Person p = new Person();   
    2. Address addr = new Address();   
    3. p.setAddress(addr);   
    4.   
    5. // 正确   
    6. session.beginTransaction();   
    7. session.save(address);   
    8. session.save(p);   
    9. session.getTransaction().commit();   
    10.   
    11. // 运行会报错,因为外键address设为了not null,在save p的时候,address_id还没有值,所以不满足非空的约束   
    12. session.beginTransaction();   
    13. session.save(p);   
    14. session.save(address);   
    15. session.getTransaction().commit();  

    因为外键address设为了not null,在save p的时候,address_id还没有值,所以不满足非空的约束



    如果说大家对Hibernate理解比较熟了,只是想看看具体配置文件怎么样写,那么到上面就可以了,如果还想探究一下Hibernate和数据库的对应关系那请继续,先看一个文件(HIbernate在建立上面的映射关系的时候产生的数据库语句)

    1. 单向   
    2. 多对一   
    3. Hibernate: create table address (address_id bigint not null, primary key (address_id))   
    4. Hibernate: create table person (person_id bigint not null, address_id bigint not null, primary key (person_id))   
    5. Hibernate: alter table person add index FK_o8tnkglv9n1eeqmo7de7em37n (address_id), add constraint FK_o8tnkglv9n1eeqmo7de7em37n foreign key (address_id) references address (address_id)   
    6.   
    7. 一对一   
    8.     基于外键   
    9. Hibernate: create table address (address_id bigint not null, primary key (address_id))   
    10. Hibernate: create table person (person_id bigint not null, address_id bigint not null, primary key (person_id))   
    11. Hibernate: alter table person add constraint UK_o8tnkglv9n1eeqmo7de7em37n unique (address_id)   
    12. Hibernate: alter table person add index FK_o8tnkglv9n1eeqmo7de7em37n (address_id), add constraint FK_o8tnkglv9n1eeqmo7de7em37n foreign key (address_id) references address (address_id)   
    13.   
    14.     基于主键   
    15. Hibernate: create table address (address_id bigint not null, primary key (address_id))   
    16. Hibernate: create table person (person_id bigint not null, primary key (person_id))   
    17. Hibernate: alter table person add index FK_acrq16tm1ioc620qk2nm5gwyg (person_id), add constraint FK_acrq16tm1ioc620qk2nm5gwyg foreign key (person_id) references address (address_id)   
    18.   
    19. 一对多   
    20. Hibernate: create table address (address_id bigint not null, person_id bigint, primary key (address_id))   
    21. Hibernate: create table person (person_id bigint not null, primary key (person_id))   
    22. Hibernate: alter table address add index FK_5k57pkctki2o1wpmk2880r74j (person_id), add constraint FK_5k57pkctki2o1wpmk2880r74j foreign key (person_id) references person (person_id)   
    23.   
    24. 单向——中间表   
    25. 一对多   
    26. Hibernate: create table address (address_id bigint not null, primary key (address_id))   
    27. Hibernate: create table per_addr (person_id bigint not null, address_id bigint not null, primary key (person_id, address_id))   
    28. Hibernate: create table person (person_id bigint not null, primary key (person_id))   
    29. Hibernate: alter table per_addr add constraint UK_8v3twe5k7nlb8wcjqvcpydab6 unique (address_id)   
    30. Hibernate: alter table per_addr add index FK_8v3twe5k7nlb8wcjqvcpydab6 (address_id), add constraint FK_8v3twe5k7nlb8wcjqvcpydab6 foreign key (address_id) references address (address_id)   
    31. Hibernate: alter table per_addr add index FK_hdwakolgq6oelbfuallvfbcn4 (person_id), add constraint FK_hdwakolgq6oelbfuallvfbcn4 foreign key (person_id) references person (person_id)   
    32.   
    33. 多对一   
    34. Hibernate: create table address (address_id bigint not null, primary key (address_id))   
    35. Hibernate: create table per_addr (peron_id bigint not null, address_id bigint not null, primary key (peron_id))   
    36. Hibernate: create table person (person_id bigint not null, primary key (person_id))   
    37. Hibernate: alter table per_addr add index FK_7xqe3kidwvogwcohihqla5ehv (peron_id), add constraint FK_7xqe3kidwvogwcohihqla5ehv foreign key (peron_id) references person (person_id)   
    38. Hibernate: alter table per_addr add index FK_8v3twe5k7nlb8wcjqvcpydab6 (address_id), add constraint FK_8v3twe5k7nlb8wcjqvcpydab6 foreign key (address_id) references address (address_id)   
    39.   
    40. 一对一   
    41. Hibernate: create table address (address_id bigint not null, primary key (address_id))   
    42. Hibernate: create table per_addr (person_id bigint not null, address_id bigint not null, primary key (person_id))   
    43. Hibernate: create table person (person_id bigint not null, primary key (person_id))   
    44. Hibernate: alter table per_addr add constraint UK_8v3twe5k7nlb8wcjqvcpydab6 unique (address_id)   
    45. Hibernate: alter table per_addr add index FK_hdwakolgq6oelbfuallvfbcn4 (person_id), add constraint FK_hdwakolgq6oelbfuallvfbcn4 foreign key (person_id) references person (person_id)   
    46. Hibernate: alter table per_addr add index FK_8v3twe5k7nlb8wcjqvcpydab6 (address_id), add constraint FK_8v3twe5k7nlb8wcjqvcpydab6 foreign key (address_id) references address (address_id)   
    47.   
    48. 多对多   
    49. Hibernate: create table address (address_id bigint not null, primary key (address_id))   
    50. Hibernate: create table per_addr (person_id bigint not null, address_id bigint not null, primary key (person_id, address_id))   
    51. Hibernate: create table person (person_id bigint not null, primary key (person_id))   
    52. Hibernate: alter table per_addr add index FK_8v3twe5k7nlb8wcjqvcpydab6 (address_id), add constraint FK_8v3twe5k7nlb8wcjqvcpydab6 foreign key (address_id) references address (address_id)   
    53. Hibernate: alter table per_addr add index FK_hdwakolgq6oelbfuallvfbcn4 (person_id), add constraint FK_hdwakolgq6oelbfuallvfbcn4 foreign key (person_id) references person (person_id)   
    54.   
    55.   
    56. 双向   
    57. 多对一/一对多   
    58. Hibernate: create table address (address_id bigint not null, primary key (address_id))   
    59. Hibernate: create table person (person_id bigint not null, address_id bigint not null, primary key (person_id))   
    60. Hibernate: alter table person add index FK_o8tnkglv9n1eeqmo7de7em37n (address_id), add constraint FK_o8tnkglv9n1eeqmo7de7em37n foreign key (address_id) references address (address_id)   
    61. 一对一   
    62.     基于外键   
    63. Hibernate: create table address (address_id bigint not null, primary key (address_id))   
    64. Hibernate: create table person (person_id bigint not null, address_id bigint not null, primary key (person_id))   
    65. Hibernate: alter table person add constraint UK_o8tnkglv9n1eeqmo7de7em37n unique (address_id)   
    66. Hibernate: alter table address add index FK_scpdoha0q1mmbp5f9lojr3s9x (address_id), add constraint FK_scpdoha0q1mmbp5f9lojr3s9x foreign key (address_id) references person (person_id)   
    67. Hibernate: alter table person add index FK_o8tnkglv9n1eeqmo7de7em37n (address_id), add constraint FK_o8tnkglv9n1eeqmo7de7em37n foreign key (address_id) references address (address_id)   
    68.        
    69.     基于主键   
    70. Hibernate: create table address (person_id bigint not null, primary key (person_id))   
    71. Hibernate: create table person (person_id bigint not null, primary key (person_id))   
    72. Hibernate: alter table address add index FK_5k57pkctki2o1wpmk2880r74j (person_id), add constraint FK_5k57pkctki2o1wpmk2880r74j foreign key (person_id) references person (person_id)   
    73.   
    74. 双向——中间表   
    75. 多对一/一对多   
    76. Hibernate: create table address (address_id bigint not null, primary key (address_id))   
    77. Hibernate: create table per_addr (address_id bigint not null, person_id bigint not null, primary key (person_id, address_id))   
    78. Hibernate: create table person (person_id bigint not null, primary key (person_id))   
    79. Hibernate: alter table per_addr add index FK_8v3twe5k7nlb8wcjqvcpydab6 (address_id), add constraint FK_8v3twe5k7nlb8wcjqvcpydab6 foreign key (address_id) references address (address_id)   
    80. Hibernate: alter table per_addr add index FK_hdwakolgq6oelbfuallvfbcn4 (person_id), add constraint FK_hdwakolgq6oelbfuallvfbcn4 foreign key (person_id) references person (person_id)   
    81.   
    82. 一对一   
    83. Hibernate: create table address (address_id bigint not null, primary key (address_id))   
    84. Hibernate: create table per_addr (person_id bigint not null, address_id bigint, primary key (address_id))   
    85. Hibernate: create table person (person_id bigint not null, primary key (person_id))   
    86. Hibernate: alter table per_addr add constraint UK_hdwakolgq6oelbfuallvfbcn4 unique (person_id)   
    87. Hibernate: alter table per_addr add index FK_hdwakolgq6oelbfuallvfbcn4 (person_id), add constraint FK_hdwakolgq6oelbfuallvfbcn4 foreign key (person_id) references person (person_id)   
    88. Hibernate: alter table per_addr add index FK_8v3twe5k7nlb8wcjqvcpydab6 (address_id), add constraint FK_8v3twe5k7nlb8wcjqvcpydab6 foreign key (address_id) references address (address_id)   
    89.   
    90. 多对多   
    91. Hibernate: create table address (address_id bigint not null, primary key (address_id))   
    92. Hibernate: create table per_addr (person_id bigint not null, address_id bigint not null, primary key (person_id, address_id))   
    93. Hibernate: create table person (person_id bigint not null, primary key (person_id))   
    94. Hibernate: alter table per_addr add index FK_8v3twe5k7nlb8wcjqvcpydab6 (address_id), add constraint FK_8v3twe5k7nlb8wcjqvcpydab6 foreign key (address_id) references address (address_id)   
    95. Hibernate: alter table per_addr add index FK_hdwakolgq6oelbfuallvfbcn4 (person_id), add constraint FK_hdwakolgq6oelbfuallvfbcn4 foreign key (person_id) references person (person_id)  

    通过上面的SQL语句,我们可以得出以下几个结论

    • 单向、双向是在对象层面上去考虑的,其实在数据库层面上是一致的,比如单向多对一和双向多对一在表结构上一样的
    • 为了提高效率一般在(中间表)外键上都会创建index

    Hibernate中的关系映射是最常用、也是最复杂的。在之前的点滴学习中对Hibernate的映射关系也是一知半解,这次特地花时间认真整理学习了一下,特别是对Hibernate和数据库中表的对应关系进行了认真的探究。

  • 相关阅读:
    轻松实现 网络视频播放器
    端口扫描 多方式协同实现
    关于部分应用无法向POJ提交代码的解决方案
    一套跨平台五子棋网游的开发经历
    SSH2.0编程 ssh协议过程实现
    ssh秘钥交换详解与实现 diffie-hellman-group-exchange-sha
    OnlineJudge 离线题库采集
    SOCKET 实现NAT 穿越
    基于公网smtp协议实现邮件服务器
    周六搞事情,微信小程序开发文档已放出!
  • 原文地址:https://www.cnblogs.com/sunshine-2015/p/5312447.html
Copyright © 2011-2022 走看看