hibernate继承关系映射关系方法(二)每个子类一张表

2015-11-28 13:38

TPS:所谓“每个子类一张表(Table Per Subclass)”:父类一张表,每个子类一张表,父类的表保存公共有信息,子类的表只保存自己特有的信息

     这种策略是使用<joined-subclass>标签来定义子类的。父类、子类都对应一张数据库表。在父类对应的数据库表中,它存储了所 有记录的公共信息,实际上该父类对应的表会包含所有的记录,包括父类和子类的记录;在子类对应的数据库表中,这个表只定义了子类中所特有的属性映射的字 段。

hibernate继承关系映射关系方法(二)每个子类一张表0hibernate继承关系映射关系方法(二)每个子类一张表1


hibernate继承关系映射关系方法(二)每个子类一张表2

person表

hibernate继承关系映射关系方法(二)每个子类一张表3

student表

hibernate继承关系映射关系方法(二)每个子类一张表4

worker表

hibernate继承关系映射关系方法(二)每个子类一张表5

测试工程:

hibernate继承关系映射关系方法(二)每个子类一张表6

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>
结果:

hibernate继承关系映射关系方法(二)每个子类一张表7
控制台打印的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=?