10 17Hibernate之继承映射

本文详细介绍了Hibernate中的三种继承映射方式:UNION-CLASS、JOINED-SUBCLASS和SUBCLASS。每种方式都有基于文件配置和基于Annotation的配置方法,讨论了它们在数据表设计、类继承关系、数据查询性能等方面的优缺点。SUBCLASS(识别器)模式是常用的,因为它在一张表中处理继承关系,由Hibernate自动维护识别字段。
摘要由CSDN通过智能技术生成

实际上从容器映射开始就应进入了多表操作的时代,而继承映射也是多表,但是在继承映射的操作之中,关注的是表的继承于类继承的对应关系,在整个Hibernate里面一共支持有如下几种继承映射关系:
(1)UNION-CLASS:每一个继承子表对应一个实体类;
(2)SUBCLASS:每个类对应一张数据表,数据表中存在有继承关系;
(3)JOINED-SUBCLASS:连接子类策略,识别器。

1 继承形式一:UNION-CLASS

这种的继承关系重点只在于程序的维护上,而数据表上依然会存在有重复数据。
范例:数据库脚本

-- 删除数据表
DROP TABLE IF EXISTS student;
DROP TABLE IF EXISTS worker;
-- 创建数据表
CREATE TABLE student(
	id VARCHAR(50),
	name VARCHAR(50),
	age INT,
	sschool VARCHAR(50),
	sscore DOUBLE,
	CONSTRAINT pk_id1 PRIMARY KEY(id)
);
CREATE TABLE worker(
	id VARCHAR(50),
	name VARCHAR(50),
	age INT,
	wcompany VARCHAR(50),
	wsalary DOUBLE,
	CONSTRAINT pk_id2 PRIMARY KEY(id)
);

此时两张数据表的创建脚本完成,而后通过这个脚本可以分析出:id、name、age三个字段在两张表中被重复定义了。但是 如果按照传统的思路,现在应该准备出两个类:

1.1 基于*.hbm.xml文件实现

在Hibernate最早的时期已经支持了这样的继承映射,所以可以直接使用*.hbm.xml文件完成此类配置。
范例:定义一个Member.java的抽象类,设置公共属性信息

package org.lks.pojo;

import java.io.Serializable;

@SuppressWarnings("serial")
public abstract class Member implements Serializable {
   
	private String id;
	private String name;
	private Integer age;
}

随后在Member类里面提供有公共的属性,那么Student或者是Worker子类就可以继承Member类。
范例:定义Student.java类

package org.lks.pojo;

@SuppressWarnings("serial")
public class Student extends Member implements java.io.Serializable {
   

	private String sschool;
	private Double sscore;

}

范例:定义Worker.java类

package org.lks.pojo;

@SuppressWarnings("serial")
public class Worker extends Member implements java.io.Serializable {
   
	private String wcompany;
	private Double wsalary;
}

从面向对象的角度来看,此时的代码已经符合于面向对象的设计要求了,重复的属性可以在子类中通过继承关系继续使用。
范例:随后的重点部分就要在映射文件的编写上了
(1)继承关系之中有一个重要的特点:所有子类对象都可以向父类对象转换,所以在进行操作的过程中对于映射文件只要求提供一个Member.hbm.xml文件即可。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
	<class name="org.lks.pojo.Member" catalog="hedb">
		<id name="id" type="java.lang.String">
			<column name="id" length="50" />
			<generator class="assigned"></generator>
		</id>
		<property name="name" type="java.lang.String">
			<column name="name" length="50" />
		</property>
		<property name="age" type="java.lang.Integer">
			<column name="age" />
		</property>
		<!-- 表示学生信息 -->
		<union-subclass name="org.lks.pojo.Student" table="student" catalog="hedb">
			<property name="sschool" type="java.lang.String">
				<column name="sschool" length="50" />
			</property>
			<property name="sscore" type="java.lang.Double">
				<column name="sscore" precision="22" scale="0" />
			</property>
		</union-subclass>
		<!-- 表示工人信息 -->
		<union-subclass name="org.lks.pojo.Worker" table="worker" catalog="hedb">
			<property name="wcompany" type="java.lang.String">
				<column name="wcompany" length="50" />
			</property>
			<property name="wsalary" type="java.lang.Double">
				<column name="wsalary" precision="22" scale="0" />
			</property>
		</union-subclass>
	</class>
</hibernate-mapping>

范例:测试学生增加

package org.lks.test;

import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.Student;

public class TestMemberInsert {
   
	public static void main(String[] args) {
   
		Student stu = new Student();
		stu.setId("stu - 1");
		stu.setName("hhy");
		stu.setAge(20);
		stu.setSschool("xxx");
		stu.setSscore(120.0);
		System.out.println(HibernateSessionFactory.getSession().save(stu));
		HibernateSessionFactory.getSession().beginTransaction().commit();
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

stu - 1
Hibernate: 
    insert 
    into
        hedb.student
        (name, age, sschool, sscore, id) 
    values
        (?, ?, ?, ?, ?)

现在如果保存的是学生信息(使用的是学生这个子类),那么SQL语句将向student表中保存。
范例:保存工人信息

package org.lks.test;

import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.Worker;

public class TestWorkerInsert {
   
	public static void main(String[] args) {
   
		Worker worker = new Worker();
		worker.setId("worker - 1");
		worker.setName("lks");
		worker.setAge(23);
		worker.setWcompany("xxx");
		worker.setWsalary(12000.0);
		System.out.println(HibernateSessionFactory.getSession().save(worker));
		HibernateSessionFactory.getSession().beginTransaction().commit();
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

worker - 1
Hibernate: 
    insert 
    into
        hedb.worker
        (name, age, wcompany, wsalary, id) 
    values
        (?, ?, ?, ?, ?)

此时发现在使用子类映射的过程之中,虽然只有一个映射的文件,但是会根据使用子类的不同找到不同的数据表进行操作。
范例:数据查询

package org.lks.test;

import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.Student;

public class TestStudentGet {
   
	public static void main(String[] args) {
   
		Student stu = (Student) HibernateSessionFactory.getSession().get(Student.class, "stu - 1");
		System.out.println(stu);
		HibernateSessionFactory.closeSession();
		System.exit(0);
	}
}

Hibernate: 
    select
        student0_.id as id1_0_0_,
        student0_.name as name2_0_0_,
        student0_.age as age3_0_0_,
        student0_.sschool as sschool1_1_0_,
        student0_.sscore as sscore2_1_0_ 
    from
        hedb.student student0_ 
    where
        student0_.id=?
Member [id=stu - 1, name=hhy, age=20]Student [sschool=xxx, sscore=120.0]

此时由于已经明确的设置好了要查询的数据类,所以直接查询具体的对应表。

但是现在有一个问题,既然是继承映射,那么所有的子类都是Member的子类,能不能够按照Member查询呢?
范例:按照Member查询数据

package org.lks.test;

import org.lks.dbc.HibernateSessionFactory;
import org.lks.pojo.Member;

public class TestMemberGet {
   
	public static void 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值