`
neeleon
  • 浏览: 175557 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

hibernate入门(九)关联关系中的高级应用_继承关系

阅读更多

3. 继承关系

在前面的部门员工实例中,我们设定的员工只是普通的员工,现在假如有SaleSkill 两类员工,它们作为Employee 的子类。如何实现这些子类的映射?为了方便以后的操作说明和不影响以前的操作,我们把前面用到的员工部门类及相关实体配置文件,主配置文件等拷贝到一个新的项目theExtend 下进行操作。

1 )共享一张表:

意思是我们把子类的当作父类来处理共同映射成一张表。

>> 步骤一,创建Employee 的子类:SaleSkill 。内容如下:

package com.asm.hibernate.domain;

public class Sale extends Employee {

    private String signSale ;

    ... 省略 getXXX setXXX()

}

  package com.asm.hibernate.domain;

public class Skill extends Employee{

    private String signSkill ;

    ... 省略 getXXX setXXX()

}

>> 步骤二、修改 Employee.hbm.xml 配置文件:

< hibernate-mapping package = "com.asm.hibernate.domain" >

    < class name = "Employee" discriminator-value = "0" >

       < id name = "id" >

           < generator class = "native" />

       </ id >

       < discriminator column = "sign" type = "string" />

       < property name = "name" ></ property >

       < many-to-one name = "depart" column = "depart_id" />

        < subclass name = "Sale" discriminator-value = "1" >

           < property name = "signSale" ></ property >

       </ subclass >

       < subclass name = "Skill" discriminator-value = "2" >

           < property name = "signSkill" ></ property >

       </ subclass >

    </ class >

</ hibernate-mapping >

配置文件说明 理解 <subclass> 元素: 它作为class 的子元素,但是它却和class 非常相似,name 同样是指所关联到的“类”,下面的 < property > 也与class 下的 < property > 一样。我们注意到它和class 均增加了一个新属性 discriminator-value ,它的作用就是配置这些类的“鉴别类型”。而 discriminator-value 的配置主要参照的是 <discriminator> 它通常称为鉴别类型,即是说鉴别属于什么类型, 因为 在涉及到继承关系的操作时,总会涉及到父子类的关系,比如在上面的配置中,我们设定了sign 子段来标识类型,执行后会再对此作说明。 注意: < discriminator > 要写在后面元素的前面,因为它的dtd 文件是这样规定得。

>> 步骤三、修改主配置文件,由于是拷贝的前面的文件,所以需要去掉无关的映射文件,否则会提示找不到这此映射文件。

>> 步骤四、编写测试类:

package com.asm.hibernate.test;

public class ManyToOneTest {

    public static void main(String[] args) {

       add ();

       Employee emp =query (2);

       System. out .println( "emp type:" +emp );

    }

     static Employee query( int empId) {

       Session s = null ;

       try {

           s = HibernateUtil.getSession ();

           Employee emp = (Employee) s.get(Employee. class , empId);

           System. out .println( "Department Name:" + emp.getDepart().getName());

           return emp;

       } finally {

           if (s != null )

              s.close();

       }

    }

     static void add() {

       Session s = null ;

       Transaction tx = null ;

       try {

           Department depart = new Department();

           depart.setName( "departName" );

 

           Employee emp = new Employee();

           emp.setName( "empName" );

           emp.setDepart(depart);

            Sale emp2 = new Sale();

           emp2.setName( "saleEmployee" );

           emp2.setSignSale( "saleName" );

           emp2.setDepart(depart);

            Skill emp3 = new Skill();

           emp3.setName( "skillEmployee" );

           emp3.setSignSkill( "skillName" );

           emp3.setDepart(depart);

            s = HibernateUtil.getSession ();

           tx = s.beginTransaction();

            s.save(emp);

           s.save(emp2);

           s.save(emp3);

           s.save(depart);

           tx.commit();

       } finally {

           if (s != null )

              s.close();

       }

    }

}

说明:没的什么可多言的,只是要注意在查询时能返回其子类型。

下面来看执行后employee 表的内容:
+----+------+---------------+-----------+----------+-----------+

| id | sign | name          | depart_id | signSale | signSkill |

+----+------+---------------+-----------+----------+-----------+

|  1 | 0    | empName       |         1 | NULL     | NULL      |

|  2 | 1    | saleEmployee  |         1 | saleName | NULL      |

|  3 | 2    | skillEmployee |         1 | NULL     | skillName |

+----+------+---------------+-----------+----------+-----------+
先来看sign 这列:由于sign 是鉴别类型设定的字段,且分别在前面为EmployeeSaleSkill 分别配置了“012 ”所以它们会在sign 体现出来。其实 < discriminator column = "sign" type = "string" /> 也可以把type 属性值设为“int ”等。
再来看“signSalesignSkill ”字段:它们本身是专为特定的类的属性配置的字段(比如在第一个<subclass> 元素下的property 子元素就配置了Sale 类的signSale 属性):所以它们只适合特定的类,而不适的类将会以null 来填充,这也就是如果采取“共享一张表”的最大缺点,它限制了我们不能在子类属性所映射的字段上设定“非空”。由于查询只涉及到一张表,所以效率较高。

2 )每个子类一张附表:

意思是每个类均会有一张表,但是它不是完整的表,因为它的一些字段还在父类的表中。即是说:公共字段放在父表中,子类子类分别放在子类所映射的表中,它们之间采取主外键关联。这样解决了上面的“不能设定为空”的缺限。接上面只需修改 Employee.hbm.xml 配置文件,修改后的内容如下:

< class name = "Employee" >

       < id name = "id" >

           < generator class = "native" />

       </ id >

       < property name = "name" ></ property >

       < many-to-one name = "depart" column = "depart_id" />

       < joined-subclass name = "Sale" >

           < key column = "sale_id" />

           < property name = "signSale" />

       </ joined-subclass >

      < joined-subclass name = "Skill" >

           < key column = "skill_id" />

           < property name = "signSkill" />

       </ joined-subclass >

</ class >

配置文件说明:当每个子类都会有一张表,在class 子元素下设定了 <joined-subclass> 元素, 它的意思就是专门指定为子类映射成一张表,特别要说明的是我们为每个子类都配置了<key> 元素,它的作用就是作为外键关联employee, 它的值也是参照class 元素的id 来生成。执行后的表内容如下:

skill

+----------+-----------+

| skill_id | signSkill |

+----------+-----------+

|        3 | skillName |

+----------+-----------+

sale

+---------+----------+

| sale_id | signSale |

+---------+----------+

|       2 | saleName |

+---------+----------+

 

employee

+----+---------------+-----------+

| id | name          | depart_id |

+----+---------------+-----------+

|  1 | empName       |         1 |

|  2 | saleEmployee  |         1 |

|  3 | skillEmployee |         1 |

+----+---------------+-----------+

执行后请留意hibernate 产生的sql 语句。

3 )联合使用表:

意思是同时使用(1 )(2 )的形式,主要目的是为了能使用鉴别类型,但同时也能“设定为非空”。同样只需要修改配置文件,修改后的内容如下:
< class name = "Employee" discriminator-value = "0" >

       < id name = "id" >

           < generator class = "native" />

       </ id >

       < discriminator column = "sign" type = "string" />

       < property name = "name" ></ property >

       < many-to-one name = "depart" column = "depart_id" />

        < subclass name = "Sale" discriminator-value = "1" >

           < property name = "signSale" ></ property >

       </ subclass >

       < subclass name = "Skill" discriminator-value = "2" >

           < join table = "skill" >

              < key column = "skill_id" />

              < property name = "signSkill" />

           </ join >

       </ subclass >

</ class >
观察上面的配置文件,不难发现我们对Sale 采取了(1 )方式,对Skill 采取了(3 )方式。同样请留意hibernatesql 语句和执行后的表。特别要说明的是:在进行操作时,由于hibernate 在进行操作时不能删除前面的相关联的表(主要是和第一种继承关系“共享一张表”时发生冲突,因为在建立的三张表,在未删除sale/skill 表时,是不能来删除employee 表,因为employee 表中的主键被另两张表关联了),所以需要手工删除表或者是直接删除数据库再建数据库。 补充:借助此例我们来看看 discriminator-value 的默认情况:如果我们在 < subclass name = "Skill" discriminator-value = "2" > 中不写 discriminator-value 配置,再来执行发现一切正常,查表发现它的sign 值为“com.asm.hibernate.domain.Skill ”即完整的类名,属于字串,所以执行正常。但当我们把 <discriminator> 中的type 属性改成int 时将会报错,因为默认不写是以完整的类名字串来作为标识,而设定typeint, 所以将不能匹配类型。

4 )每个具体类一张完整表:

与第(2 )种情况相比,它的主要特点就是为每个具体类建立一张表,表的字段对应子类本身的属性,同样也包括父类的所有属性。 同样只需要修改配置文件如下:

< class name = "Employee" >

       < id name = "id" >

           < generator class = "hilo" />

       </ id >

       < property name = "name" ></ property >

       < many-to-one name = "depart" column = "depart_id" />

       < union-subclass name = "Sale" >

           < property name = "signSale" />

        </union-subclass>
        <union-subclass name="Skill">
            <property name="signSkill" />
        </union-subclass>
    </class>
注意:id生成器选择了“hilo”,由于我们为每个具体类都映射了一张表,所以id不能只在每张表中递增,如果只在每张表中递增,这里的三张表中的id将会出现重复,这样我们在采用多态查询,将会查出多种结果,我们应让id是唯一的,所以采取了hilo的方式来生成id,它能保证id是全局性的递增生成,这样每张表中的id均不会重复。 同样请注意,可能需要删除某些表或者是删库建库才能执行测试类。 执行完成后,需留意hibernate产生的sql语句和表的结构内容。 补充说明:在使用这种方法时,如果父类为抽象类也是可行得,我们可以在<class>元素中配置abstract=”true”来说明父类为抽象类,自然就不会为其建表。
总结:在上面的继续关系中我们多次用到了删库建库,在执行测试类时,如果出现sql不能更新或者sql相关的错误,则不防尝试此方法。另外在学继承关系时,除了注意配置文件外,更应注意hibernate产生的sql语句以及执行后产生表的情况。通常我们建议表的数目不要超过类的数目。

分享到:
评论

相关推荐

    Hibernate_3.2.0_符合Java习惯的关系数据库持久化

    1. Hibernate入门 1.1. 前言 1.2. 第一部分 - 第一个Hibernate应用程序 1.2.1. 第一个class 1.2.2. 映射文件 1.2.3. Hibernate配置 1.2.4. 用Ant构建 1.2.5. 启动和辅助类 1.2.6. 加载并存储对象 1.3. 第...

    Hibernate3.1_学习源码

    案例目录: 01 01Hibernate_Handwork : 手工配置使用Hibernate,其中详细标了...07 07Hibernate_Mapping : Hibernate中的数据关联技术,是一个重点又是一个难点,演示了 一对一、多对一、一对多、多对多等几种情况。

    Hibernate+中文文档

    1. Hibernate入门 1.1. 前言 1.2. 第一部分 - 第一个Hibernate应用程序 1.2.1. 第一个class 1.2.2. 映射文件 1.2.3. Hibernate配置 1.2.4. 用Ant构建 1.2.5. 启动和辅助类 1.2.6. 加载并存储对象 1.3. 第...

    hibernate3.2中文文档(chm格式)

    1. Hibernate入门 1.1. 前言 1.2. 第一部分 - 第一个Hibernate应用程序 1.2.1. 第一个class 1.2.2. 映射文件 1.2.3. Hibernate配置 1.2.4. 用Ant构建 1.2.5. 启动和辅助类 1.2.6. 加载并存储对象 1.3. 第...

    hibernate(基于MVC的服务器架构技术)

    是在是学习hibernate必备之;良材料 Hibernate基础入门,Hibernate基本API,Hibernate物件关联映射,继承映射和容器映射关系映射

    Hibernate中文详细学习文档

    1. Hibernate入门 1.1. 前言 1.2. 第一部分 - 第一个Hibernate应用程序 1.2.1. 第一个class 1.2.2. 映射文件 1.2.3. Hibernate配置 1.2.4. 用Ant构建 1.2.5. 启动和辅助类 1.2.6. 加载并存储对象 1.3. 第...

    Hibernate 中文 html 帮助文档

    1. Hibernate入门 1.1. 前言 1.2. 第一部分 - 第一个Hibernate应用程序 1.2.1. 第一个class 1.2.2. 映射文件 1.2.3. Hibernate配置 1.2.4. 用Ant构建 1.2.5. 启动和辅助类 1.2.6. 加载并存储对象 1.3. 第...

    HibernateAPI中文版.chm

    1. Hibernate入门 1.1. 前言 1.2. 第一部分 - 第一个Hibernate应用程序 1.2.1. 第一个class 1.2.2. 映射文件 1.2.3. Hibernate配置 1.2.4. 用Ant构建 1.2.5. 启动和辅助类 1.2.6. 加载并存储对象 1.3. 第...

    Hibernate框架参考文档

    1. Hibernate入门; 2. 体系结构(Architecture); 3. 配置; 4. 持久化类(Persistent Classes); 5. 对象/关系数据库映射基础(Basic O/R Mapping); 6. 集合类(Collections)映射; 7. 关联关系映射; 8. 组件(Component)...

    ORM及Hibernate介绍.pptx

    ORM及Hibernate介绍,包括ORM及Hibernate简介,Hibernate入门学习,Hibernate数据持久化,Hibernate缓存的使用,实体关联关系映射,实体继承关系映射,Hibernate查询语言

    Hibernate教程

    2. Hibernate入门 2.1. 前言 2.2. 第一部分 - 第一个Hibernate程序 2.2.1. 第一个class 2.2.2. 映射文件 2.2.3. Hibernate配置 2.2.4. 用Ant编译 2.2.5. 安装和帮助 2.2.6. 加载并存储对象 2.3. 第二部分 ...

    hibernate3.04中文文档.chm

    2. Hibernate入门 2.1. 前言 2.2. 第一部分 - 第一个Hibernate程序 2.2.1. 第一个class 2.2.2. 映射文件 2.2.3. Hibernate配置 2.2.4. 用Ant编译 2.2.5. 安装和帮助 2.2.6. 加载并存储对象 2.3. ...

    hibernate 体系结构与配置 参考文档(html)

    1. Hibernate入门 1.1. 前言 1.2. 第一部分 - 第一个Hibernate应用程序 1.2.1. 第一个class 1.2.2. 映射文件 1.2.3. Hibernate配置 1.2.4. 用Ant构建 1.2.5. 启动和辅助类 1.2.6. 加载并存储对象 1.3. 第...

    经典JAVA.EE企业应用实战.基于WEBLOGIC_JBOSS的JSF_EJB3_JPA整合开发.pdf

    这个项目包括5个实体,这5个实体之间具有复杂的关联关系,而且业务逻辑也相对复杂,希望让读者理论联系实际,真正将jsf+ejb 3+jpa整合真正运用到实际开发中。该案例采用目前最流行、最规范的java ee架构,整个应用...

    Hibernate3的帮助文档

    2. Hibernate入门 2.1. 前言 2.2. 第一部分 - 第一个Hibernate程序 2.2.1. 第一个class 2.2.2. 映射文件 2.2.3. Hibernate配置 2.2.4. 用Ant编译 2.2.5. 安装和帮助 2.2.6. 加载并存储对象 2.3. 第二部分 ...

    Hibernate参考文档

    1. Hibernate入门 1.1. 前言 1.2. 第一部分 - 第一个Hibernate应用程序 1.2.1. 第一个class 1.2.2. 映射文件 1.2.3. Hibernate配置 1.2.4. 用Ant构建 1.2.5. 启动和辅助类 1.2.6. 加载并存储对象 1.3. 第...

    hibernate 框架详解

    2. Hibernate入门 2.1. 前言 2.2. 第一部分 - 第一个Hibernate程序 2.2.1. 第一个class 2.2.2. 映射文件 2.2.3. Hibernate配置 2.2.4. 用Ant编译 2.2.5. 安装和帮助 2.2.6. 加载并存储对象 2.3. 第二...

    java从入门到精通70个PPT

    43 Hibernate 关联映射 44 HQL实用技术 45 HQL高级 46 Criteria 查询 47-49 项目实战 影院信息查询系统 50 pl/sql 51 Oracle数据库对象 52 提高数据库性能 53 hibernate总结 54 使用Spring容器管理JavaBean 55 ...

    Grails 中文参考手册

    5.2.1 GORM中的关联 5.2.1.1 一对一 5.2.1.2 一对多 5.2.1.3 多对多 5.2.2 GORM的组合 5.2.3 GORM的继承 5.2.4 集合、列表和映射 5.3 持久化基础 5.3.1 保存和更新 5.3.2 删除对象 5.3.3 级联更新和删除 5.3.4 立即...

Global site tag (gtag.js) - Google Analytics