继承关系映射

  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();

       }

    }

}

 

某公司雇员(Employee)包括经理(Manager),技术人员(Technician)和销售员(Salesman)。开发部经理(DeveloperManger),既是经理也是技术人员。销售部经理(SalesManager),既是经理也是销售员。 以Employee类为虚基类派生出Manager,Technician和Salesman类;再进一步派生出Developermanager和Salesmanager类。 Employee类的属性包括姓名、职工号、工资级别,月薪(实发基本工资加业绩工资)。操作包括月薪计算函数(pay()),该函数要求输入请假天数,扣去应扣工资后,得出实发基本工资。 Technician类派生的属性有每小时附加酬金和当月工作时数,及研究完成进度系数。业绩工资为三者之积。也包括同名的pay()函数,工资总额为基本工资加业绩工资。 Salesman类派生的属性有当月销售额和酬金提取百分比,业绩工资为两者之积。也包括同名的pay()函数,工资总额为基本工资加业绩工资。 Manager类派生属性有固定奖金额和业绩系数,业绩工资为两者之积。工资总额也为基本工资加业绩工资。 而DeveloperManager类,pay()函数是将作为经理和作为技术人员业绩工资之和的一半作为业绩工资。 SalesManager类,pay()函数则是经理的固定奖金额的一半,加上部门总销售额与提成比例之积,这是业绩工资。 编程实现工资管理。特别注意pay()的定义和调用方法:先用同名覆盖,再用运行时多态。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值