继承映射详解

来源:互联网 发布:金属材料牌号查询软件 编辑:程序博客网 时间:2024/06/05 05:40

一、继承映射


       继承是面向对象很重要的特性,它实现了代码的服用,在关系模型中同样也有继承关系,这种继承关系其实可以看做是一种枚举关系,一种类型中可以枚举出很多子类型,这些子类型和父对象形成了继承关系,能够对其进行枚举的大部分都可以看做是一种继承映射,所以这种枚举关系可以看做是继承映射,例如动物就是一种抽象类,它是其它动物猪、猫等的父类,它们之间就是一种继承关系,如下图:

       

       这种继承映射在转化为关系模型后会生成一张表,那么这张表是如何区分这两种类型的呢?用的是关系字段,需要在表中添加类型字段,使用关键字来标明对象的类型。所以上图中的对象模型对应的表结构如下:       

       在生成表结构时,需要添加对应的字段类型,所以需要在映射文件中添加对应的映射鉴别器,这里就需要使用discriminator-value属性。


  1.1、类文件

      类文件中没有需要注意的地方,在编写时注意之间的继承关系即可。

      清单一:Animal类代码,只需要添加基本的属性。


  1. package com.src.hibernate;  
  2.   
  3. public class Animal {  
  4.       
  5.     //id号  
  6.     private int id;  
  7.     public int getId() {  
  8.         return id;  
  9.     }  
  10.     public void setId(int id) {  
  11.         this.id = id;  
  12.     }  
  13.       
  14.     //名称  
  15.     private String name;  
  16.     public String getName() {  
  17.         return name;  
  18.     }  
  19.     public void setName(String name) {  
  20.         this.name = name;  
  21.     }  
  22.       
  23.     //性别  
  24.     private boolean sex;  
  25.     public boolean isSex() {  
  26.         return sex;  
  27.     }  
  28.     public void setSex(boolean sex) {  
  29.         this.sex = sex;  
  30.     }  
  31. }  

        清单二:Bird和Pig类,添加基本的属性,并继承Animal类。

  1. package com.src.hibernate;  
  2. public class Bird extends Animal {  
  3.   
  4.     //高度  
  5.     private int height;  
  6.     public int getHeight() {  
  7.         return height;  
  8.     }  
  9.     public void setHeight(int height) {  
  10.         this.height = height;  
  11.     }  
  12.       
  13. }  
  14.   
  15. package com.src.hibernate;  
  16. public class Pig extends Animal {  
  17.       
  18.     //重量  
  19.     private int weight;  
  20.     public int getWeight() {  
  21.         return weight;  
  22.     }  
  23.     public void setWeight(int weight) {  
  24.         this.weight = weight;  
  25.     }  
  26. }  

  1.2、映射文件

       映射文件中需要添加对应的映射,该模型中只需要添加一个映射文件,因为只生成一张表,在映射文件中添加对应的子类映射,使用<subclass>标签,标签中添加鉴别器discriminator-value,该鉴别器属性指明了在数据库中写入数据时指示写入的是何种类型,如下:

  1. <?xml version="1.0"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC   
  3.     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
  4.     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  5. <hibernate-mapping>  
  6.     <class name="com.src.hibernate.Animal" table="t_animal">  
  7.         <id name="id">  
  8.             <generator class="native"/>  
  9.         </id>  
  10.         <!-- 加入鉴别标签,且必须放在id后面 -->  
  11.         <discriminator column="type" />  
  12.         <property name="name"/>  
  13.         <property name="sex" type="boolean"/>  
  14.           
  15.         <subclass name="com.src.hibernate.Pig" discriminator-value="P">  
  16.             <property name="weight"/>  
  17.         </subclass>  
  18.         <subclass name="com.src.hibernate.Bird" discriminator-value="B">  
  19.             <property name="height"/>  
  20.         </subclass>  
  21.     </class>  
  22.   
  23. </hibernate-mapping>  

  1.3、分析结果

       生成的mysql数据库表中不仅会添加Animal的基本属性,而且会添加Pig和Bird的属性,因为在映射文件中使用<subclass>写出了所添加的属性,另外还添加了相应的鉴别器属性,所以在数据库中会添加对应的鉴别列,生成的表结构如下图:


二、数据操作


  2.1 写入数据

       在进行数据读取和写入操作时需要注意类中的操作使用了

  1. public void testSave(){  
  2.     Session session=null;  
  3.     try{  
  4.         //创建session对象  
  5.         session=HibernateUtils.getSession();  
  6.         //开启事务  
  7.         session.beginTransaction();  
  8.           
  9.         Pig pig=new Pig();  
  10.         pig.setName("小猪猪");  
  11.         pig.setSex(true);  
  12.         pig.setWeight(200);  
  13.         session.save(pig);  
  14.           
  15.         Bird bird=new Bird();  
  16.         bird.setName("xiaoniaoniao");  
  17.         bird.setSex(true);  
  18.         bird.setHeight(100);  
  19.         session.save(bird);  
  20.           
  21.         session.getTransaction().commit();  
  22.     }catch(Exception e){  
  23.         e.printStackTrace();  
  24.         session.getTransaction().rollback();  
  25.     }finally{  
  26.         HibernateUtils.closeSession(session);  
  27.     }  
  28.   
  29. }  

  2.2  多态查询--get和hql


        前几篇文章已经讨论了基本的查询方法,只需要使用load和get方法即可,这里重点讨论多态查询。多态查询是指Hibernate在加载对象时能够采用instanceof鉴别出其真正的类型的对象即可为多态查询。
       Note:多态查询不支持延迟加载,也就是说如果使用load方法,需要在映射文件中将延迟加载设置为false。


    2.2.1 load延迟加载

       load支持延迟加载,在加载对象时其实生成的是对象的代理,所以在使用多态查询时需要在映射文件中将延迟加载设置为false,如下:

  1. <?xml version="1.0"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC   
  3.     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
  4.     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  5. <hibernate-mapping>  
  6.     <class name="com.src.hibernate.Animal" table="t_animal" lazy="false">  
  7.         <id name="id">  
  8.             <generator class="native"/>  
  9.         </id>  
  10.         <!-- 加入鉴别标签,且必须放在id后面 -->  
  11.         <discriminator column="type" />  
  12.         <property name="name"/>  
  13.         <property name="sex" type="boolean"/>  
  14.           
  15.         <subclass name="com.src.hibernate.Pig" discriminator-value="P">  
  16.             <property name="weight"/>  
  17.         </subclass>  
  18.         <subclass name="com.src.hibernate.Bird" discriminator-value="B">  
  19.             <property name="height"/>  
  20.         </subclass>  
  21.     </class>  
  22. </hibernate-mapping>  

      load加载方法,使用load加载该示例中支持多态查询,在配置文件中将延迟加载设置为false,所以这里使用load方法能够加载获得相应的对象类。

  1. public void testLoad(){  
  2.     Session session=null;  
  3.     try{  
  4.         session=HibernateUtils.getSession();  
  5.         session.beginTransaction();  
  6.           
  7.         Animal ani=(Animal)session.load(Animal.class,1);  
  8.         System.out.println(ani.getName());  
  9.         //因为load默认支持lazy,所以我们看到的是Animal的代理  
  10.         //所以采用了instanceof无法鉴别出真正的类型Pig  
  11.         //所以load在此情况下是不支持多态查询的  
  12.         if(ani instanceof Pig){  
  13.             System.out.println("我是小猪猪!");  
  14.         }else{  
  15.             System.out.println("我不是小猪猪!");  
  16.         }  
  17.         session.getTransaction().commit();  
  18.     }catch(Exception e){  
  19.         e.printStackTrace();  
  20.         session.getTransaction().rollback();  
  21.     }finally{  
  22.         HibernateUtils.closeSession(session);  
  23.     }  
  24. }  

    2.2.2 hql查询

         hql支持多态查询,这主要由于查询出的是一个真正的对象,并不会返回一个代理,所以hql支持多态查询,另外在查询时需要注意查询语句中不要使用表名,而是要使用类名称,Hibernate会根据类名称将其映射为对应的表名称,如下:

  1. public void testLoad5(){  
  2.     Session session=null;  
  3.     try{  
  4.         session=HibernateUtils.getSession();  
  5.         session.beginTransaction();  
  6.           
  7.         List<Animal> list=session.createQuery("from Animal").list();  
  8.         for(Iterator iter=list.iterator();iter.hasNext();){  
  9.             Animal a=(Animal)iter.next();  
  10.             if(a instanceof Pig){  
  11.                 System.out.println("我是小猪猪!");  
  12.             }else{  
  13.                 System.out.println("我不是小猪猪!");  
  14.             }  
  15.         }  
  16.         session.getTransaction().commit();  
  17.     }catch(Exception e){  
  18.         e.printStackTrace();  
  19.         session.getTransaction().rollback();  
  20.     }finally{  
  21.         HibernateUtils.closeSession(session);  
  22.     }  
  23. }  

查询结果:

  1. Hibernate: select animal0_.id as id0_, animal0_.name as name0_, animal0_.sex as sex0_, animal0_.weight as weight0_, animal0_.height as height0_, animal0_.type as type0_ from t_animal animal0_  
  2. 我是小猪猪!  
  3. 我不是小猪猪!  
  4. 我是小猪猪!  
  5. 我不是小猪猪!  


结语


        继承映射是对象模型中重要的关系映射,通过使用继承映射能够将继承关系转换为对应的关系表,在配置映射文件时需要使用<subclass>标签,另外还需要在标签中添加鉴别器属性来标明不同的类型,在操作读取时才能很快的鉴别出相应的类型。

0 0
原创粉丝点击