hibernate继承关系映射方法(三)--每个具体类一张表TPC

时间:2021-08-08 14:45:51

TPC:所谓是“每个具体类一张表(table per concrete class)”的意思是:使继承体系中每一个子类都对应数据库中的一张表每一个子类对应的数据库表都包含了父类的信息,并且包含了自己独有的属性。每个子类对应一张表,而且这个表的信息是完备的,即包含了所有从父类继承下来的属性映射的字段。这种策略是使用<union-subclass>标签来定义子类的。

hibernate继承关系映射方法(三)--每个具体类一张表TPChibernate继承关系映射方法(三)--每个具体类一张表TPC

注意:三个类+一个父类映射文件+两张表

hibernate继承关系映射方法(三)--每个具体类一张表TPC

student表

hibernate继承关系映射方法(三)--每个具体类一张表TPC

worker表

hibernate继承关系映射方法(三)--每个具体类一张表TPC

测试工程:

hibernate继承关系映射方法(三)--每个具体类一张表TPC

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 String sno;    //学号
       private String school;  //学校
    	
	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 String wno;      //工号
     private Double salary;   //工资
   

	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

<?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">  
    <!-- table per concrete(TPC) (a. 具体的,实际的) -->  
    <!-- 每一个具体类一张表 -->  
    <!-- 虚拟选项为'true' -->  
    <class name="Person" table="person" abstract="true">  <!-- 多设置一个属性abstract="true",因为根本就没有person表 -->
    <id column="Id" name="id" type="integer">  
        <!-- 主键的生成策略为'分配' -->  
        <generator class="assigned"></generator>  
    </id>  
    <property column="Name" name="name" type="string"></property>  
    <property column="Sex" name="sex" type="string"></property>  
    <property column="Age" name="age" type="integer"></property>  <!-- 公共属性 -->
      
    <!--student具体类-->  
    <union-subclass name="Student" table="student">  
        <property column="Sno" name="sno" type="string"></property>      <!-- 特征属性 --> 
        <property column="School" name="school" type="string"></property>  <!-- 特征属性 -->
    </union-subclass>  
      
    <!--worker具体类-->  
    <union-subclass name="Worker" table="worker">  
        <property column="Wno" name="wno" type="string"></property>  <!-- 特征属性 -->
        <property column="Salary" name="salary" type="double"></property>  <!-- 特征属性 -->
    </union-subclass>  
      
    </class>  
</hibernate-mapping>  
<union-subclass>标签是用于指示出该hbm文件所表示的类的子类,如Person类有两个子 类,就需要两个<union-subclass>标签以此类推。

<union-subclass>标签的"name"属性用于指 定子类的全限定名称,"table"属性用于指定该子类对应的表的名称,"extends"属性用于指定该子类的父类,

注意:"extends"属性与<union-subclass>标签的位置有关,若<union-subclass>标签作为<class>标签的子标签,则"extends"属性可以不设置,否则需要明确设置"extends"属性。

<class>标签中的"abstract"属性如果值为true则,不会生成表结构。如果值为false则会生成表结构,但是不会插入数据。

数据库文件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 {
     //保存学生信息
	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_.Id,
        student_.Name as Name0_,
        student_.Sex as Sex0_,
        student_.Age as Age0_,
        student_.Sno as Sno1_,
        student_.School as School1_ 
    from
        student student_ 
    where
        student_.Id=?
Hibernate: 
    insert 
    into
        student
        (Name, Sex, Age, Sno, School, Id) 
    values
        (?, ?, ?, ?, ?, ?)
*/
	//加载学生信息
	 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_.Id as Id0_0_,
        student0_.Name as Name0_0_,
        student0_.Sex as Sex0_0_,
        student0_.Age as Age0_0_,
        student0_.Sno as Sno1_0_,
        student0_.School as School1_0_ 
    from
        student student0_ 
    where
        student0_.Id=?*/
	//保存工人信息
		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_.Id,
        worker_.Name as Name0_,
        worker_.Sex as Sex0_,
        worker_.Age as Age0_,
        worker_.Wno as Wno2_,
        worker_.Salary as Salary2_ 
    from
        worker worker_ 
    where
        worker_.Id=?
        Hibernate: 
    insert 
    into
        worker
        (Name, Sex, Age, Wno, Salary, Id) 
    values
        (?, ?, ?, ?, ?, ?)
*/
		//加载工人信息
		 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_.Id as Id0_0_,
        worker0_.Name as Name0_0_,
        worker0_.Sex as Sex0_0_,
        worker0_.Age as Age0_0_,
        worker0_.Wno as Wno2_0_,
        worker0_.Salary as Salary2_0_ 
    from
        worker worker0_ 
    where
        worker0_.Id=?

		
*/
	
}
测试页面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的继承关系(三)每个具体类一张表TPC</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的继承关系(三)--每个具体类一张表TPC</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()); //加载子类对象
               
               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>
测试结果:

hibernate继承关系映射方法(三)--每个具体类一张表TPC
student表插入的值:

hibernate继承关系映射方法(三)--每个具体类一张表TPC

worker表插入的值:

hibernate继承关系映射方法(三)--每个具体类一张表TPC
控制台打印店的HQL

Hibernate: 
    select
        student_.Id,
        student_.Name as Name0_,
        student_.Sex as Sex0_,
        student_.Age as Age0_,
        student_.Sno as Sno1_,
        student_.School as School1_ 
    from
        student student_ 
    where
        student_.Id=?
Hibernate: 
    insert 
    into
        student
        (Name, Sex, Age, Sno, School, Id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    select
        student0_.Id as Id0_0_,
        student0_.Name as Name0_0_,
        student0_.Sex as Sex0_0_,
        student0_.Age as Age0_0_,
        student0_.Sno as Sno1_0_,
        student0_.School as School1_0_ 
    from
        student student0_ 
    where
        student0_.Id=?
Hibernate: 
    select
        worker_.Id,
        worker_.Name as Name0_,
        worker_.Sex as Sex0_,
        worker_.Age as Age0_,
        worker_.Wno as Wno2_,
        worker_.Salary as Salary2_ 
    from
        worker worker_ 
    where
        worker_.Id=?
Hibernate: 
    insert 
    into
        worker
        (Name, Sex, Age, Wno, Salary, Id) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    select
        worker0_.Id as Id0_0_,
        worker0_.Name as Name0_0_,
        worker0_.Sex as Sex0_0_,
        worker0_.Age as Age0_0_,
        worker0_.Wno as Wno2_0_,
        worker0_.Salary as Salary2_0_ 
    from
        worker worker0_ 
    where
        worker0_.Id=?