TPC:所谓是“每个具体类一张表(table per concrete class)”的意思是:使继承体系中每一个子类都对应数据库中的一张表。每一个子类对应的数据库表都包含了父类的信息,并且包含了自己独有的属性。每个子类对应一张表,而且这个表的信息是完备的,即包含了所有从父类继承下来的属性映射的字段。这种策略是使用<union-subclass>标签来定义子类的。
注意:三个类+一个父类映射文件+两张表
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 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>测试结果:
student表插入的值:
worker表插入的值:
控制台打印店的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=?