继承映射

本文深入探讨了ORM映射中的级联操作、inverse属性以及不同继承映射方式的特点。介绍了cascade选项的作用,inverse如何控制关联关系的维护,并详细解析了一张表、每子类一张表等多种继承映射方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、

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>中设置级联。

 

 

二、inservse

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

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

       注: 配置成one-to-one的对象不维护关联关系。inservse是集合的属性,但不适用在list集合中,因为这样list的顺序会失效。

 

例如:一对多中,在one这方放弃维护关联关系:

<map name="emps" inverse="true">

    <key column="depart_id"/>

    <map-key type="long" column="name"/>

    <one-to-many class="Employee"/>

</map>

放弃前:

Hibernate: insert into Department (name) values (?)

Hibernate: insert into Employee (name, depart_id) values (?, ?)

Hibernate: insert into Employee (name, depart_id) values (?, ?)

Hibernate: update Employee set depart_id=?, name=? where id=?

Hibernate: update Employee set depart_id=?, name=? where id=?

放弃后:

Hibernate: insert into Department (name) values (?)

Hibernate: insert into Employee (name, depart_id) values (?, ?)

Hibernate: insert into Employee (name, depart_id) values (?, ?)

 

三、继承映射:

优点:方便。

缺点:但是每增加一个子类,就会改变表employee的结构,还有大量的null值。

方式一:一个类继承体系一张表

整个的集成体系用一张表,设计一张表employee:

type字段是一个由hibrnate自动生成的鉴别器,用来区分员工类型的。

       Id   name   depart_id   type    skill        sell

                                0      null         null    普通员工

                                1      coding       null    销售员

                                2      null         100      技术员

   

1、分别编写Skiller类和sell类,均继承employee类;

2、在映射文件中:每个子类不能设置为not null。

    <?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" discriminator-value="0">

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

           <generator class="native"/>

       </id>

       <discriminator column="type" type="int"/>  <!-- 鉴别器。hibrnate 用来区分不同的子类-->

       <property name="name" unique="true"/>

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

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

           <property name="skill"/>

       </subclass>

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

           <property name="sell"/>

       </subclass>

    </class>

</hibernate-mapping>

3、编写测试类:

public class TestExtends {

    public static void main(String[] args) {

       // TODO Auto-generated method stub

       //add();

       query(2);

    }

    public static Department add(){

       Session s=null;

       Transaction tx=null;

       try{

           s=HibrnateUtil.getSession();

           tx=s.beginTransaction();

          

           Department dep=new Department();

           dep.setName("department one");

          

           Employee e1=new Employee();

           e1.setName("aaa");

           e1.setDepart(dep);

          

           Skiller e2=new Skiller();

           e2.setName("bbb");

           e2.setDepart(dep);

           e2.setSkill("skill");

          

           Sales e3=new Sales();

           e3.setName("ccc");

           e3.setDepart(dep);

           e3.setSell(100);

          

           s.save(dep);

           s.save(e1);

           s.save(e2);

           s.save(e3);

           tx.commit();

           return dep;

       }finally{

           if(s!=null){

              s.close();

           }

       }

    }

   

    public static void query(int id){

       Session s=null;

       Transaction tx=null;

       try{

           s=HibrnateUtil.getSession();

           tx=s.beginTransaction();

          

           Employee e=(Employee)s.get(Employee.class, id);

           System.out.println("员工名字:"+e.getName());

           System.out.println("员工类型:"+e.getClass());

          

           tx.commit();

       }finally{

           if(s!=null){

              s.close();

           }

       }

    }

}

执行结果:

插入结果:

执行结果:只在一张表中查询。效率高。

 

方式二:每个子类一张表,存放子类所特有的属性,公共的属性是放在父类employee中的。

    没有大量的null,大事表格数量多。

 

1、  在配置文件中:

 

    <class name="Employee">

   

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

           <generator class="native"/>

       </id>

       <property name="name" unique="true"/>

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

       <joined-subclass name="Skiller"> <!-- 子类单独映射成一张表 -->

           <key column=" employee_id "/><!-- 子类的外键 -->

           <property name="skill"/><!-- 子类的属性 -->

       </joined-subclass>

       <joined-subclass name="Sales">

           <key column="employee_id "/>

           <property name="sell"/>

       </joined-subclass>

      

</class>

 

在测试类中:

插入结果:

查询结果:有两个左外连接。效率不高。

Hibernate: select employee0_.id as id3_0_, employee0_.name as name3_0_, employee0_.depart_id as depart3_3_0_, employee0_1_.skill as skill4_0_, employee0_2_.sell as sell5_0_, case when employee0_1_.employee_id is not null then 1 when employee0_2_.employee_id is not null then 2 when employee0_.id is not null then 0 end as clazz_0_ from Employee employee0_ left outer join Skiller employee0_1_ on employee0_.id=employee0_1_.employee_id left outer join Sales employee0_2_ on employee0_.id=employee0_2_.employee_id where employee0_.id=?

 

 

 

 

方式三:

    混合使用“一个类继承体系一张表”和“每个子类一张表” (表结构)

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

    <id name="id">

        <generator class="native"/>

    </id>

    <discriminator column="type"/>

    <property name="name"/>

    <subclass name="Skiller">

        <property name="net"/>

    </subclass>

    <subclass name=”Sales”">

        <join table="sales">

           <key column="employee_id"/>

           <property name="sell"/>

        </join>

    </subclass>

</class>

 

执行结果:

查询结果:查询时,表格employee会和表格sales连接查询。

Hibernate: select employee0_.id as id3_0_, employee0_.name as name3_0_, employee0_.depart_id as depart4_3_0_, employee0_.skill as skill3_0_, employee0_1_.sell as sell4_0_, employee0_.type as type3_0_ from Employee employee0_ left outer join sales employee0_1_ on employee0_.id=employee0_1_.employee_id where employee0_.id=?

 

 

方式四:

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

<class name="Employee" abstract="true">

    <id name="id">

        <generator class="hilo"/>

    </id>

    <property name="name"/>

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

        <property name="skill"/>

    </union-subclass>

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

        <property name="sell"/>

    </union-subclass>   

</class>

主健不能是identity类型,如果父类是abstract=”true”就不会有表与之对应。

隐式多态,映射文件没有联系,限制比较多很少使用。

 

执行结果:

插入结果:

Hibernate: insert into Department (name) values (?)

Hibernate: insert into Employee (name, depart_id, id) values (?, ?, ?)

Hibernate: insert into Skiller (name, depart_id, skill, id) values (?, ?, ?, ?)

Hibernate: insert into Sales (name, depart_id, sell, id) values (?, ?, ?, ?)

查询结果:子查询

Hibernate: select employee0_.id as id3_0_, employee0_.name as name3_0_, employee0_.depart_id as depart3_3_0_, employee0_.skill as skill4_0_, employee0_.sell as sell5_0_, employee0_.clazz_ as clazz_0_ from ( select id, name, depart_id, order_id, null as skill, null as sell, 0 as clazz_ from Employee union select id, name, depart_id, order_id, skill, null as sell, 1 as clazz_ from Skiller union select id, name, depart_id, order_id, null as skill, sell, 2 as clazz_ from Sales ) employee0_ where employee0_.id=?

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值