`
啸笑天
  • 浏览: 3433778 次
  • 性别: Icon_minigender_1
  • 来自: China
社区版块
存档分类
最新评论

Hibernate的4种继承关系

阅读更多

一、继承关系_整个继承树映射到一张表

对象模型(Java类结构)

一个类继承体系一张表(subclass)(表结构)


Employee.java

package com.taobao.hibernate.domain;
public class Employee {
	private int id;
	private String name;
	private Department department;

	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Department getDepartment() {
		return department;
	}
	public void setDepartment(Department department) {
		this.department = department;
	}
}

 

Skiller.java

 

package com.taobao.hibernate.domain;
public class Skiller extends Employee {
	private String skill;

	public String getSkill() {
		return skill;
	}

	public void setSkill(String skill) {
		this.skill = skill;
	}
	
}

 

Sales.java

 

package com.taobao.hibernate.domain;
public class Sales extends Employee {
	private String sell;

	public String getSell() {
		return sell;
	}

	public void setSell(String sell) {
		this.sell = sell;
	}
}

 

 

这里我们考虑设计数据库是把员工都涉及在一张表,那么如何区分员工种类呢?加入员工类型这个字段来区别。

只需更改Employee.hbm.xml

 

<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE hibernate-mapping PUBLIC  
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  
<hibernate-mapping package="domain">  
    <class name="Employee" discriminator-value="0">  
        <id name="id">  
            <generator class="native"/>  
        </id>  
        <discriminator column="type" type="int"></discriminator>  
        <property name="name"></property>     
        <many-to-one name="dpt" column="dpt_id" lazy="false"></many-to-one>  
        <subclass name="Skiller" discriminator-value="1">  
            <property name="skill" ></property>  
        </subclass>  
        <subclass name="Sales" discriminator-value="2">  
            <property name="sell"></property>  
        </subclass>  
    </class>  
</hibernate-mapping> 

 

<discriminator column="type" type="int"/>中的type默认值是string。

所有子类定义的字段不能为空。

使用了<discriminator column="type" type="int"></discriminator>这个标签,就是映射了type字段,然后Hibernate会根据type字段的值来确定从数据库中取过来的是什么对象。

在查询的get方法时,也可以自动识别,会自动用相对应的对象去封装数据。

 

一个继承树映射到一张表的话,会有很多空字段,不符合关系数据库的设计模式。

二、继承关系_每个类映射到一张表



 这时候Employee.hbm.xml配置文件信息如下:

 

<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE hibernate-mapping PUBLIC  
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  
<hibernate-mapping package="domain">  
    <class name="Employee">  
        <id name="id">  
            <generator class="native"/>  
        </id>  
        <property name="name"></property>     
        <many-to-one name="dpt" column="dpt_id" lazy="false"></many-to-one>  
        <joined-subclass name="Skiller">  
            <key column="employee_id"></key>  
            <property name="skill"></property>  
        </joined-subclass>  
        <joined-subclass name="Sales">  
            <key column="employee_id"></key>  
            <property name="sell"></property>  
        </joined-subclass>  
    </class>  
</hibernate-mapping>  

 <joined-subclass name="Sales">

子类对应类名为Sales,表名为Sales

         <key column="employee_id"></key>

通过employee_id与Employee表关联

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

设置sell属性

</joined-subclass>

这样就完成了Hibernate的配置,生成的表符合上面所说的表结构。

 

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

插入部门

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

插入销售员工到员工表

Hibernate: insert into Sales (sell, employee_id) values (?, ?)

插入销售员工到销售员工表

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

插入技术员工到员工表

Hibernate: insert into Skiller (skill, employee_id) values (?, ?)

插入技术员工到技术员工表

5条插入信息

现在又有问题了,既然用到了多表关联,那么删除这些级联操作会怎么样呢

Hibernate: delete from Sales where employee_id=?

Hibernate: delete from Employee where id=?

发现两条delete语句很好的将员工信息删除掉了。

这里还需要注意的是,查询的时候避免使用多态查询,多表连接查询效率较低,最好明确指定查询的类别,不要直接用员工类进行查询。

 

三、继承关系_鉴别器与内连接相结合

把属性不多的类对应的列放到父类列中,把子类属性多的单独用一个表。这里假设Sales有很多列

内容和上两篇没有什么大的区别,原理类似,只是标签上略有不同。

Employee.hbm.xml

 

<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE hibernate-mapping PUBLIC  
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  
<hibernate-mapping package="domain">  
    <class name="Employee" discriminator-value="0">  
        <id name="id">  
            <generator class="native"/>  
        </id>  
        <discriminator column="type" type="int"/>  
        <property name="name"></property>     
        <many-to-one name="dpt" column="dpt_id" lazy="false"></many-to-one>  
        <subclass name="Skiller" discriminator-value="1">  
                <property name="skill"></property>        </subclass>  
        <subclass name="Sales" discriminator-value="2">  
                <join table="sales">  
            <key column="employee_id"></key>  
            <property name="sell"></property>  
                </join>  
        </joined-subclass>  
    </class>  
</hibernate-mapping>  

 

四、继承关系_每.类映射一张独立表



 可见表之间都是独立的,没有关联的。

Employee.hbm.xml

 

<?xml version="1.0" encoding="UTF-8"?>  
<!DOCTYPE hibernate-mapping PUBLIC  
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
<hibernate-mapping package="domain">  
    <class name="Employee">  
        <id name="id">  
            <generator class="hilo"/>  
        </id>  
        <property name="name"></property>     
        <many-to-one name="dpt" column="dpt_id" lazy="false"></many-to-one>  
        <union-subclass name="Skiller">  
            <property name="skill"></property>  
        </union-subclass>  
        <union-subclass name="Sales">  
            <property name="sell"></property>  
        </union-subclass>  
    </class>  
</hibernate-mapping>  

 这种方式的局限在于,如果一个属性在超类中做了映射,其字段名必须与所有子类表中定义的相同(Hibernate可能在后续版本中放宽此限制)。除此之外,使用union-subclass映射策略是不可使用identity的主键生成策略,因为同一类继承层次中所有实体类都需要使用同一个主键种子(即多个持续化实体对应的记录的主键是连续的)。受此影响,也不应该使用native主键生成策略,因为native会根据数据库来选择使用identity或sequence策略。,所以不要native,identity,sequence主键生成策略,可以是increment,hilo。

如果父类是abstract=”true”就不会有表与之对应。 

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

 

 

  • 大小: 15.6 KB
  • 大小: 31.2 KB
  • 大小: 32.4 KB
  • 大小: 6 KB
  • 大小: 10.9 KB
分享到:
评论
1 楼 zyz251314 2012-12-09  
你好  第一种情况中  就是所有的都放在一张数据库表中的情况
如果我有N个子类,但是我要查询 M (M<N) 个子类的合集我该怎么查询?
 

相关推荐

Global site tag (gtag.js) - Google Analytics