TPS:所谓“每个子类一张表(Table Per Subclass)”:父类一张表,每个子类一张表,父类的表保存公共有信息,子类的表只保存自己特有的信息
这种策略是使用<joined-subclass>标签来定义子类的。父类、子类都对应一张数据库表。在父类对应的数据库表中,它存储了所 有记录的公共信息,实际上该父类对应的表会包含所有的记录,包括父类和子类的记录;在子类对应的数据库表中,这个表只定义了子类中所特有的属性映射的字 段。
person表
student表
worker表
测试工程:
Person.java
package com.hust.PO;
public class Person {
private Integer id;
private String name; //姓名
private Integer age; //年龄
private String sex; //性别
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
Student.java
package com.hust.PO;
public class Student extends Person {
private Integer sid; //学生标识,与父类person内连接
private String sno; //学号
private String school; //学校
public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public String getSno() {
return sno;
}
public void setSno(String sno) {
this.sno = sno;
}
public String getSchool() {
return school;
}
public void setSchool(String school) {
this.school = school;
}
}
Worker.java
package com.hust.PO;
public class Worker extends Person {
private Integer wid; //工人标识,与父类person内连接
private String wno; //工号
private Double salary; //工资
public Integer getWid() {
return wid;
}
public void setWid(Integer wid) {
this.wid = wid;
}
public String getWno() {
return wno;
}
public void setWno(String wno) {
this.wno = wno;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
}
映射文件Person.hbm.xml:
<joined-subclass>标签需要包含一个key标签,这个标签指定了子类和父类之间是通过哪个字段来内连接的。
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.hust.PO">
<!-- Person表 -->
<class name="Person" table="person">
<!-- person 表保存公共属性 -->
<id name="id">
<!-- 父类的主键生成策略为‘分配’ -->
<generator class="assigned"></generator>
</id>
<property name="name" column="Name" type="string"></property>
<property name="sex" column="Sex" type="string"></property>
<property name="age" column="Age" type="java.lang.Integer"></property>
<!-- student表 ,name是类名。table是对应的表名-->
<joined-subclass name="Student" table="student">
<key column="Sid"></key> <!-- 指定了子类和父类之间是通过哪个字段来关联的 ,这里的关联是内连接-->
<property column="Sno" name="sno" type="string" ></property> <!-- 子类特征属性 -->
<property column="School" name="school" type="string" ></property> <!-- 子类特征属性 -->
</joined-subclass>
<!-- worker表 -->
<joined-subclass name="Worker" table="worker">
<key column="Wid"></key>
<property column="Wno" name="wno" type="string" ></property> <!-- 子类特征属性 -->
<property column="Salary" name="salary" type="double" ></property> <!-- 子类特征属性 -->
</joined-subclass>
</class>
</hibernate-mapping>
数据库Dao文件,TableDao.java
package com.hust.Dao;
import org.hibernate.Session;
import org.hibernate.Transaction;
import SessionFactory.HibernateSessionFactory;
import com.hust.PO.Student;
import com.hust.PO.Worker;
public class TableDao {
//保存学生信息,执行段代码后,student对象的id,name,sex,age会自动保存在person表中,特征属性sid,sno,school会保存在student表中,person表的Id字段和student表的Sid字段是内连接的
public void saveStu(Student stu){
Session session=HibernateSessionFactory.getSession();
Transaction ts=null;
try{
ts=session.beginTransaction();
session.saveOrUpdate(stu);
ts.commit();
}catch(Exception ex){
ts.rollback();
System.out.println("添加学生信息失败");
}finally{
HibernateSessionFactory.closeSession();
}
}
/*session.saveOrUpdate(stu);控制台打印的HQL
Hibernate:
select
student_.Sid,
student_1_.Name as Name0_,
student_1_.Sex as Sex0_,
student_1_.Age as Age0_,
student_.Sno as Sno1_,
student_.School as School1_
from
student student_
inner join
person student_1_
on student_.Sid=student_1_.id
where
student_.Sid=?
Hibernate:
insert
into
person
(Name, Sex, Age, id)
values
(?, ?, ?, ?)
Hibernate:
insert
into
student
(Sno, School, Sid)
values
(?, ?, ?)*/
//加载学生信息,过程是参数id与person表内连接,查询person表的公共字段和student表的特征字段
public Student loadStu(Integer id){
Session session=HibernateSessionFactory.getSession();
Transaction ts=null;
Student stu=null;
try{
ts=session.beginTransaction();
stu=(Student)session.get(Student.class, id);
ts.commit();
}catch(Exception ex){
ts.rollback();
System.out.println("加载学生信息失败");
}finally{
HibernateSessionFactory.closeSession();
}
return stu;
}
/* stu=(Student)session.get(Student.class, id);控制台打印的HQL
Hibernate:
select
student0_.Sid as id0_0_,
student0_1_.Name as Name0_0_,
student0_1_.Sex as Sex0_0_,
student0_1_.Age as Age0_0_,
student0_.Sno as Sno1_0_,
student0_.School as School1_0_
from
student student0_
inner join //与person表的Id内连接
person student0_1_
on student0_.Sid=student0_1_.id
where
student0_.Sid=? //参数id是student表的Sid字段
*/
//保存工人信息,执行段代码后,worker对象的id,name,sex,age会自动保存在person表中,特征属性wid,wno,salary会保存在worker表中,person表的Id字段和worker表的Wid字段是内连接的
public void saveWorker(Worker worker){
Session session=HibernateSessionFactory.getSession();
Transaction ts=null;
try{
ts=session.beginTransaction();
session.saveOrUpdate(worker);
ts.commit();
}catch(Exception ex){
ts.rollback();
System.out.println("添加工人信息失败");
}finally{
HibernateSessionFactory.closeSession();
}
}
/*session.saveOrUpdate(worker);控制台打印的HQL
Hibernate:
select
worker_.Wid,
worker_1_.Name as Name0_,
worker_1_.Sex as Sex0_,
worker_1_.Age as Age0_,
worker_.Wno as Wno2_,
worker_.Salary as Salary2_
from
worker worker_
inner join
person worker_1_
on worker_.Wid=worker_1_.id
where
worker_.Wid=?
Hibernate:
insert
into
person
(Name, Sex, Age, id)
values
(?, ?, ?, ?)
Hibernate:
insert
into
worker
(Wno, Salary, Wid)
values
(?, ?, ?)*/
//加载工人信息,过程是参数id与person表内连接,查询person表的公共字段和woker表的特征字段
public Worker loadWorker(Integer id){
Session session=HibernateSessionFactory.getSession();
Transaction ts=null;
Worker worker=null;
try{
ts=session.beginTransaction();
worker=(Worker)session.get(Worker.class, id);
ts.commit();
}catch(Exception ex){
ts.rollback();
System.out.println("加载工人信息失败");
}finally{
HibernateSessionFactory.closeSession();
}
return worker;
}
/*worker=(Worker)session.get(Worker.class, id);控制台打印的HQL
Hibernate:
select
worker0_.Wid as id0_0_,
worker0_1_.Name as Name0_0_,
worker0_1_.Sex as Sex0_0_,
worker0_1_.Age as Age0_0_,
worker0_.Wno as Wno2_0_,
worker0_.Salary as Salary2_0_
from
worker worker0_
inner join //与person表内连接
person worker0_1_
on worker0_.Wid=worker0_1_.id
where
worker0_.Wid=?//参数id与worker的表的Wid字段内连接
*/
}
测试页面test.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page import="com.hust.Dao.*" %>
<%@ page import="com.hust.PO.*" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>hibernate的继承关系(二)每个子类一张表</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<h2>hibernate的继承关系(二)每个子类一张表</h2>
<hr>
<%
//新建学生对象
Student stu=new Student();
stu.setId(new Integer(1));
stu.setName("tuke");
stu.setAge(new Integer(22));
stu.setSex("nan");
stu.setSno("M201571885");
stu.setSchool("华中科技大学");
//保存stu对象
TableDao dao=new TableDao();
dao.saveStu(stu);
//从数据库中获取stu对象
Student stu1=dao.loadStu(stu.getId()); //加载子类对象的时候,会使用内连接语句inner join
out.println("<br>数据库中的学生姓名:"+stu1.getName()); //共有属性
out.println("<br>数据库中的学生学号:"+stu1.getSno()); //特征属性
out.println("<br>数据库中的学生学校:"+stu1.getSchool()); //特征属性
out.println("<br>");
//新建工人对象
Worker worker=new Worker();
worker.setId(new Integer(2));
worker.setName("李四");
worker.setAge(new Integer(34));
worker.setSex("nan");
worker.setWno("W20152223");
worker.setSalary(new Double(5435.32));
//保存工人对象
dao.saveWorker(worker);
//从数据库中获取工人对象
Worker worker2=dao.loadWorker(worker.getId()); //加载子类对象的时候,会使用内连接语句inner join、
out.println("<br>数据库中的工人姓名:"+worker2.getName()); //共有属性
out.println("<br>数据库中的工人工号:"+worker2.getWno()); //特征属性
out.println("<br>数据库中的工人工资:"+worker2.getSalary());//特征属性
%>
</body>
</html>
结果:
控制台打印的HQL:
Hibernate:
select
student_.Sid,
student_1_.Name as Name0_,
student_1_.Sex as Sex0_,
student_1_.Age as Age0_,
student_.Sno as Sno1_,
student_.School as School1_
from
student student_
inner join
person student_1_
on student_.Sid=student_1_.id
where
student_.Sid=?
Hibernate:
insert
into
person
(Name, Sex, Age, id)
values
(?, ?, ?, ?)
Hibernate:
insert
into
student
(Sno, School, Sid)
values
(?, ?, ?)
Hibernate:
select
student0_.Sid as id0_0_,
student0_1_.Name as Name0_0_,
student0_1_.Sex as Sex0_0_,
student0_1_.Age as Age0_0_,
student0_.Sno as Sno1_0_,
student0_.School as School1_0_
from
student student0_
inner join
person student0_1_
on student0_.Sid=student0_1_.id
where
student0_.Sid=?
Hibernate:
select
worker_.Wid,
worker_1_.Name as Name0_,
worker_1_.Sex as Sex0_,
worker_1_.Age as Age0_,
worker_.Wno as Wno2_,
worker_.Salary as Salary2_
from
worker worker_
inner join
person worker_1_
on worker_.Wid=worker_1_.id
where
worker_.Wid=?
Hibernate:
insert
into
person
(Name, Sex, Age, id)
values
(?, ?, ?, ?)
Hibernate:
insert
into
worker
(Wno, Salary, Wid)
values
(?, ?, ?)
Hibernate:
select
worker0_.Wid as id0_0_,
worker0_1_.Name as Name0_0_,
worker0_1_.Sex as Sex0_0_,
worker0_1_.Age as Age0_0_,
worker0_.Wno as Wno2_0_,
worker0_.Salary as Salary2_0_
from
worker worker0_
inner join
person worker0_1_
on worker0_.Wid=worker0_1_.id
where
worker0_.Wid=?