Hibernate核心思想—ORM机制(三)

来源:互联网 发布:linux 查cpu核心数 编辑:程序博客网 时间:2024/06/15 00:35
上篇博文中总结的一对多和多对多实体类的映射。本次总结实体类继承的映射机制。实体类的继承映射常用的共有三种方式。一一来看。

(八)继承映射(1)单表继承,每棵继承树使用一个表

        这种方法是一个继承的树总共生成一张表,因为类继承树肯定是对应多个类,所以如果要把多个类的信息存放在一张表中,必须有某种机制来区分哪些记录是属于哪个类的。这种机制就是,在表中添加一个字段。

         用这个字段的值来进行区分。用hibernate实现这种策略的时候,有如下步骤:

        1、父类用普通的<class>标签定义在父类中定义一个discriminator,即指定这个区分的字段的名称和类型。

               如:<discriminatorcolumn=”XXX” type=”string”/>

        2、子类使用<subclass>标签定义,在定义subclass的时候,需要注意如下几点:

              Subclass标签的name属性是子类的全路径名

              在Subclass标签中,用discriminator-value属性来标明本子类的discriminator字段(用来区分不同类的字段)的值Subclass标签,既可以被class标签所包含(这种包含关系,表明了类之间的继承关系),也可以与class标签平行。当subclass标签的定义与class标签平行的时候,需要在subclass标签中,添加extends属性,里面的值是父类的全路径名称。

        3、子类的其它属性,像普通类一样,定义在subclass标签的内部。

        举例:


        Type就是鉴别值,P表示为猪,B表示为鸟。

        Animal.java

[java] view plaincopyprint?
  1. public class Animal { 
  2.      private int id;   
  3.      private String name;   
  4.      private boolean sex; 
  5.   //………省略get和set方法 
  6. } 


Pig.java

[java] view plaincopyprint?
  1. public class Pigextends Animal { 
  2.      private int weight; 
  3. //………省略get和set方法 

Brid.java

[java] view plaincopyprint?
  1. public class Birdextends Animal { 
  2.      private int height; 
  3. //………省略get和set方法 


Animal.hbm.xml

[html] view plaincopyprint?
  1. <?xmlversion="1.0"?> 
  2. <!DOCTYPE hibernate-mapping PUBLIC 
  3.      "-//Hibernate/HibernateMapping DTD 3.0//EN" 
  4.      "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 
  5. <hibernate-mappingpackage="com.wh.hibernate"> 
  6.      <class name="Animal"table="t_animal"lazy="false"> 
  7.             <id name="id"> 
  8.                    <generatorclass="native"/> 
  9.             </id> 
  10. <!--规定在表中新加的鉴别字段为名为type,类型是string,会在数据库中自动转换成数据库支持的字符类型。--> 
  11.             <discriminator column="type"type="string"/> 
  12. <!--两个普通属性--> 
  13.             <property name="name"/> 
  14.             <property name="sex"/> 
  15. <!--定义子类对象,并描述对应的鉴别值--> 
  16.             <subclass name="Pig"discriminator-value="P"> 
  17. <!--属于这个子类的特殊属性--> 
  18.                    
  19. <property name="weight"/> 
  20.             </subclass> 
  21.             <subclass name="Bird"discriminator-value="B"> 
  22.                    <property name="height"/> 
  23.             </subclass> 
  24.      </class> 
  25. </hibernate-mapping> 

         关于鉴别值在存储的时候hibernate会自动存储,不用手动赋值,在加载的时候会根据鉴别值取得相关的对象。

需要注意的一点是,鉴别字段的定义必须放到Id的后面。

(九)继承映射(2)具体表继承,每个子类一个表

        这种策略是使用joined-subclass标签来定义子类的。父类、子类,每个类都对应一张数据库表。

        在父类对应的数据库表中,实际上会存储所有的记录,包括父类和子类的记录;在子类对应的数据库表中,这个表只定义了子类中所特有的属性映射的字段。子类与父类,通过相同的主键值来关联。

        实现这种策略的时候,有如下步骤:

        1、父类用普通的<class>标签定义即可,父类不再需要定义discriminator字段

        2、子类用<joined-subclass>标签定义,在定义joined-subclass的时候,需要注意如下几点:

             Joined-subclass标签的name属性是子类的全路径名

             Joined-subclass标签需要包含一个key标签,这个标签指定了子类和父类之间是通过哪个字段来关联的。

             如:<keycolumn=”PARENT_KEY_ID”/>,这里的column,实际上就是父类的主键对应的映射字段名称。

             Joined-subclass标签,既可以被class标签所包含(这种包含关系正是表明了类之间的继承关系),也可以与class标签平行。当Joined-subclass标签的定义与class标签平行的时候,需要在Joined-subclass标签中,添加extends属性,里面的值是父类的全路径名称。

       3、子类的其它属性,像普通类一样,定义在joined-subclass标签的内部。

       举例:

     

       还是上面的例子,用第一种方法生成一个表,用第二种方法就是生成的三个表。

       实体类的写法与(八)中的相同。重点看映射文件。

Animal.hbm.xml

[html] view plaincopyprint?
  1. <?xmlversion="1.0"?> 
  2. <!DOCTYPE hibernate-mapping PUBLIC 
  3.        "-//Hibernate/HibernateMapping DTD 3.0//EN" 
  4.        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 
  5. <hibernate-mappingpackage="com.wh.hibernate"> 
  6.        <class name="Animal"table="t_animal"> 
  7.               <idname="id"> 
  8.                      <generatorclass="native"/> 
  9.               </id> 
  10. <!--两个普通属性--> 
  11.               <property name="name"/> 
  12.               <property name="sex"/> 
  13. <!--使用Joined-subclass标签,说明这个类是class的子类,生成一个单独的表t_pig--> 
  14.               <joined-subclass name="Pig"table="t_pig"> 
  15. <!--就是主表中的id,自动关联--> 
  16.                      <keycolumn="pid"/> 
  17. <!--子类的普通属性--> 
  18.                      <property name="weight"/> 
  19.               </joined-subclass> 
  20.               <joined-subclass name="Bird"table="t_bird"> 
  21.                      <key column="bid"/> 
  22.                      <property name="height"/> 
  23.               </joined-subclass> 
  24.        </class> 
  25. </hibernate-mapping> 


(十)继承映射(3)类表继承,每个具体类一个表

         这种继承策略是把父类当作一个抽象类,不生成父类表,把每个继承父类的子类生成一张表。每个子表中都有父类的属性。

         使用union-subclass标签来定义子类的。每个子类对应一张表,而且这个表的信息是完备的,即包含了所有从父类继承下来的属性映射的字段,这就是它跟joined-subclass的不同之处,joined-subclass定义的子类的表,只包含子类特有属性映射的字段。实现这种策略的时候,有如下步骤:

         1、父类用普通<class>标签定义即可

         2、子类用<union-subclass>标签定义,在定义union-subclass的时候,需要注意如下几点:

               Union-subclass标签不再需要包含key标签(与joined-subclass不同)

               Union-subclass标签,既可以被class标签所包含(这种包含关系正是表明了类之间的继承关系),也可以与class标签平行。当Union-subclass标签的定义与class标签平行的时候,需要在Union-subclass标签中,添加extends属性,里面的值是父类的全路径名称。

        3、子类的其它属性,像普通类一样,定义在Union-subclass标签的内部。这个时候,虽然在union-subclass里面定义的只有子类的属性,但是因为它继承了父类,所以,不需要定义其它的属性,在映射到数据库表的时候,依然包含了父类的所有属性的映射字段。


        举例,还是上面的例子,实体类都相同,重点是映射文件。

Animal.hbm.xml

[html] view plaincopyprint?
  1. <?xmlversion="1.0"?> 
  2. <!DOCTYPE hibernate-mapping PUBLIC 
  3.        "-//Hibernate/HibernateMapping DTD 3.0//EN" 
  4.        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 
  5. <hibernate-mappingpackage="com.wh.hibernate"> 
  6. <!--将Animal的类型设置为true,表明不生成实体表--> 
  7.        <class name="Animal" abstract="true"> 
  8.               <id name="id"> 
  9. <!--注意ID的生成策略,不能是native--> 
  10.                      <generatorclass="assigned"/> 
  11.               </id> 
  12.      <!--两个普通属性--> 
  13.               <property name="name"/> 
  14.               <property name="sex"/> 
  15.      <!--表明继承关系,集成了父类的属性,表名为t_pig--> 
  16.               <union-subclass name="Pig" table="t_pig"> 
  17.                      <property name="weight"/> 
  18.               </union-subclass> 
  19.               <union-subclass name="Bird"table="t_bird"> 
  20.                      <property name="height"/> 
  21.               </union-subclass> 
  22.        </class> 
  23. </hibernate-mapping> 


        其中animal是抽象的父类,所以不用生成表,,而且pig表和bird表中的id是不能重复的,虽然他们是两张表,但都是animal对象,所以id不能使用native自增,因为系统自增会产生相同的id,所以可以使用uuid或者自定义assigned进行手动分配。

  

       三种继承方式的优劣:

       单表继承的优点是一个表进行存取,效率高,执行速度快。但是同样因为字段多的原因存在数据冗余。

       每个子类一张表的优点是层次清楚,数据不冗余。但是如果类的继承层次多,表就会很多,那样进行读取时查询关联较多,效率比较低。

       每个具体类一张表总的还说还可以,只是不能使用native主键自增,子表的id不能相同控制起来比较麻烦。

       综合考虑,一般建议使用第一种单表继承方式进行映射。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 考驾照怕过不了怎么办 学车对车没感觉怎么办 居住证到期2个月怎么办 生育险差一个月怎么办 驾照扣了38分怎么办 新疆转入山东上学怎么办手续 驾照过日期换证怎么办 机动车被扣24分怎么办 车辆被扣24分怎么办 现在深圳牌十年老车怎么办? 护士证过期4年了怎么办 护士资格证延续注册过期了怎么办 护士资格证过期没注册怎么办 护士资格证注册时间过期怎么办 辅警体检视力不行怎么办 护士延续注册体检怀孕怎么办 护士资格证没有延续注册怎么办 申请信用卡没有座机号码怎么办 网上申请信用卡没有座机号码怎么办 我叫上门服务被骗了怎么办 上门服务被骗了3000多怎么办 微信被骗9000元怎么办 奥迪a8气囊灯亮怎么办 驾考站岗迟到了怎么办 老板欠员工工资不给怎么办 如果有一天我没头发了怎么办 苏州公积金密码忘了怎么办 科二考试第二把怎么办 科一老是记不住怎么办 科目二考试没去怎么办 网约车驾龄不到怎么办 科四预约不上怎么办 教练不退钱怎么办找谁 驾考出入证丢了怎么办 科二成绩单丢了怎么办 考驾照的准考证丢了怎么办 驾考预约去不了怎么办 科目一预约没去怎么办 打狂犬疫苗期间感冒了怎么办 公司社保欠费不交怎么办 25号社保不交怎么办欠费