继承映射

来源:互联网 发布:淘宝卖家回复评价语 编辑:程序博客网 时间:2024/06/04 23:31

 

继承映射的四种方式的映射文件。优点以及缺点

继承映射

cascade和inverse (Employee – Department)

1、  Casade用来说明当对主对象进行某种操作时是否对其关联的从对象也作类似的操作,常用的cascade:

       none,all,save-update ,delete, lock,refresh,evict,replicate,persist,

       merge,delete-orphan(one-to-many) 。一般对many-to-one,many-to-many不设置级联,在<one-to-one>和<one-to-many>中设置级联。

2、  inverse表“是否放弃维护关联关系”(在Java里两个对象产生关联时,对数据库表的影响),在one-to-many和many-to-many的集合定义中使用,inverse=”true”表示该对象不维护关联关系;该属性的值一般在使用有序集合时设置成false(注意hibernate的缺省值是false)。

       one-to-many维护关联关系就是更新外键。many-to-many维护关联关系就是在中间表增减记录。

       注: 配置成one-to-one的对象不维护关联关系

 

课上小实例:

继承的映射:

方式一:

       整个的继承体系就用一张表。设计一张表employee,表结构

字段有    id        name       depart_id        type                      skill              sell            

                                                         0代表普通员工          null           null

                                                         1代表技术员                coding      null

                                                         2代表销售员                    null       销售数量

 

(1)新建子类Skiller.java和Sales.java类:继承父类Employee,也有自己的属性

(2)分析表结构

(3)映射文件employee.hbm.xml

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC

    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

 

<hibernate-mapping

    package="com.hbsi.domain">

<!-- 方式一 -->

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

       <id name="id" column="id">

           <generator class="native"/>

       </id>

       <!-- 定义鉴别器     type属性用来定义鉴别器的类型-->

       <discriminator column="type" type="int"/>

      

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

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

       <!-- 它的子类的映射 -->

       <subclass name="Skiller"  discriminator-value="0"><!-- 用来描述子类 discriminator-value="0",用来定义鉴别器的值-->

       <property name="skill"/><!-- 特有的属性,不能加上not-null这样的属性,它是允许为空的! -->

       </subclass>

      

       <subclass name="Sales"  discriminator-value="0">

       <property name="sell"/>

       </subclass>

    </class>

</hibernate-mapping>

type--------鉴别器

       <!-- 定义鉴别器     type属性用来定义鉴别器的类型-->

       <discriminator column="type" type="int"/>

 

这种方法的缺点:关系模型不是很合理。

优点:效率高。

 

方式二:

每个子类一张表,不是存放子类的完整信息,而是存放子类所特有的属性的信息。子类共有的属性是放在employee中的。

employee             skiller              sales

id name depart_id    employee_id skill   employee_id sell

映射文件:

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC

    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

 

<hibernate-mapping

    package="com.hbsi.domain">

<!-- 方式二 -->

    <class name="Employee" table="employee">

       <id name="id">

       <generator class="native"/>

       </id>

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

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

      

       <!-- 一个子类映射 -->

       <joined-subclass name="Skiller" table="skiller">

           <key column="employee_id"/>

           <property name="skill"/>

       </joined-subclass>

      

       <joined-subclass name="Sales" table="sales">

           <key column="employee_id"/>

           <property name="sell"/>

       </joined-subclass>

    </class>

</hibernate-mapping>

 

以上两种方式都不是完美的,

优点:表格设计合理,没有大量没null的字段

缺点:效率不高。

 

方式三:

    方式一和方式二混合使用,一个类继承体系一张表和每个子类一张表。

employee                           sales               

id name depart_id type skill       employee_id sell

映射文件:

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC

    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

 

<hibernate-mapping

    package="com.hbsi.domain">

    <!-- 方式三 -->

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

       <id name="id">

           <generator class="native"/>

       </id>

       <!-- 设置鉴别器 -->

       <discriminator column="type" type="int"></discriminator>

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

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

      

       <!-- 子类型 -->

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

           <property name="skill"/>

       </subclass>

      

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

           <join table="sales">

              <key column="employee_id"/>

              <property name="sell"/>

           </join>

       </subclass>

    </class>

</hibernate-mapping>

 

优点:可以适当的解决效率的问题和设计表格的问题,选用的时候,可以将复杂的子类或者是子类的特有属性比较多的时候,可以将此子类新建一张表。如果字段少,则可加入在父类对应的表的字段中。

缺点:关系有点复杂,如果出现多个,则会关系太过复杂

方式四:

    每个具体类一张表,保存的是子类的完整信息。

 

映射文件:

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC

    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

 

<hibernate-mapping

    package="com.hbsi.domain">

    <!-- 方式四 -->

    <class name="Employee" table="employee">

       <id name="id">

           <generator class="hilo"/>

       </id>

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

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

      

       <union-subclass name="Skiller" table="skiller">

           <property name="skill"/>

       </union-subclass>

      

       <union-subclass name="Sales" table="sales">

           <property name="sell"/>

       </union-subclass>

    </class>

</hibernate-mapping>

这中方法设计三张与子类相关的表。每张表为对应类的所有属性(包括从超类继承的属性)定义相应字段。

缺点:如果一个属性在超类中做了映射,其字段名必须与所有子类表中定义的相同。不允许在联合子类的继承层次中使用标识生成器策略,实际上,主键的种子不得不为同意继承层次中的全部联合子类所共用。

最后:编写测试类TestExtends.java

package com.hbsi.test;

import org.hibernate.Hibernate;

import org.hibernate.Session;

import org.hibernate.Transaction;

import com.hbsi.domain.Department;

import com.hbsi.domain.Employee;

import com.hbsi.domain.Sales;

import com.hbsi.domain.Skiller;

import com.hbsi.hibernate.utils.HibernateUtil;

public class TestExtends {

    public static void main(String[] args) {

       // TODO Auto-generated method stub

       add();

       //查询

       System.out.println("-------------查询的结果----------------");

       query(1);

    }

    static void add(){

       Session s=null;

       Transaction tx=null;

       try{

           s=HibernateUtil.getSession();

           tx=s.beginTransaction();

           //增加

           Department depart=new Department();

           depart.setName("department one");

          

           Employee emp1=new Employee();

           emp1.setName("aaa");

           emp1.setDepart(depart);

          

           Skiller emp2=new Skiller();

           emp2.setName("bbb");

           emp2.setDepart(depart);

           emp2.setSkill("coding");

          

           Sales emp3=new Sales();

           emp3.setName("ccc");

           emp3.setDepart(depart);

           emp3.setSell(1000);

           //保存

           s.save(emp1);

           s.save(emp2);

           s.save(emp3);

           s.save(depart);

           //提交事务

           tx.commit();

       }finally{

           if(s!=null)

              s.close();

       }

    }

    static void query(int empId){

       Session s=null;

       Transaction tx=null;

       try{

           s=HibernateUtil.getSession();

           tx=s.beginTransaction();

           //查询

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

           System.out.println("员工的姓名:"+emp.getName()+" ,员工类型 :"+emp.getClass());

           if(emp instanceof Skiller){

              ((Skiller) emp).getSkill();

           }else if(emp instanceof Sales){

              ((Sales) emp).getSell();

           }

           //提交

           tx.commit();

       }finally{

           if(s!=null)

              s.close();

       }

    }

}

 

原创粉丝点击