上一篇介绍了hibernate的继承映射关系,类继承树映射成一张表;该篇介绍第二种继承映射关系:每个子类映射成一张表,所谓“每个子类一张表”:父类一张表,每个子类一张表,父类的表保存公共有信息,子类的表只保存自己特有的信息
这种策略是使用<joined-subclass>标签来定义子类的。父类、子类都对应一张数据库表。在父类对应的数据库表中,它存储了所 有记录的公共信息,实际上该父类对应的表会包含所有的记录,包括父类和子类的记录;在子类对应的数据库表中,这个表只定义了子类中所特有的属性映射的字段
Mysql建表如图所示
Person类:
package com.hiberbate.manytomany;
public class Person {
private int id;
private String name;
private int age;
private String sex;
public int getId(){
return id;
}
public void setId(int id){
this.id = id;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public int getAge(){
return age;
}
public void setAge(int age){
this.age = age;
}
public String getSex(){
return sex;
}
public void setSex(String sex){
this.sex = sex;
}
}
Worker类:
package com.hiberbate.manytomany;
public class Worker extends Person{
private int wid;
private String wno;
private String salary;
public int getWid(){
return wid;
}
public void setWid(int wid){
this.wid = wid;
}
public String getWno(){
return wno;
}
public void setWno(String wno){
this.wno = wno;
}
public String getSalary(){
return salary;
}
public void setSalary(String salary){
this.salary = salary;
}
}
Student类:
package com.hiberbate.manytomany;
public class Student extends Person{
private int sid;
private String sno;
private String school;
public int getSid(){
return sid;
}
public void setSid(int 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;
}
}
映射文件tb_persons.hbm.xml:<joined-subclass>标签需要包含一个key标签,这个标签指定了子类和父类之间是通过哪个字段来内连接的。表示子类对应表中记录的主键,这个主键与父类表中记录的主键一一对应;子类的特有属性同样用<property>
定义即可。
<?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 package="com.hiberbate.manytomany">
<class name="Person" table="tb_persons">
<id name="id" column="id" type="int" >
<!-- 父类的主键生成策略为‘分配’ -->
<generator class="assigned" />
</id>
<property name="name" type="string">
<column name="name"/>
</property>
<property name="sex" type="string" column="sex"></property>
<property name="age" type="int" column="age"></property>
<!-- student表 ,name是类名。table是对应的表名-->
<joined-subclass name="Student" table="tb_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="tb_worker">
<key column="wid"></key>
<property column="wno" name="wno" type="string" ></property> <!-- 子类特征属性 -->
<property column="salary" name="salary" type="string" ></property> <!-- 子类特征属性 -->
</joined-subclass>
</class>
</hibernate-mapping>
测试代码类
添加数据测试函数
private static void joinsubclassforsave() {
Session session = null;
//新建学生对象
Student stu = new Student();
stu.setId(10);
stu.setName("张三");
stu.setAge(new Integer(22));
stu.setSex("男");
stu.setSno("100120122016");
stu.setSchool("华中科技大学");
//新建工人对象
Worker worker=new Worker();
worker.setId(8);
worker.setName("李四");
worker.setAge(26);
worker.setSex("男");
worker.setWno("W20121224");
worker.setSalary("8000");
try {
session = HibernateUtil.getSession();
//添加数据
session.beginTransaction();
session.save(stu);
session.save(worker);
session.getTransaction().commit();
} catch (Exception e) {
session.getTransaction().rollback();
System.out.print("数据库添加失败");
e.printStackTrace();
}finally{
HibernateUtil.closeSession();
}
}
测试结果:
查询测试:
private static void joinsubclassforquery() {
Session session = null;
try {
session = HibernateUtil.getSession();
//添加数据
session.beginTransaction();
Student stu=(Student)session.get(Student.class, 10);
System.out.println("数据库中的学生姓名:"+ stu.getName()); //共有属性
System.out.println("数据库中的学生学号:"+stu.getSno()); //特征属性
System.out.println("数据库中的学生学校:"+stu.getSchool()); //特征属性
//从数据库中获取工人对象
Worker worker = (Worker)session.get(Worker.class, 8); //加载子类对象的时候,会使用内连接语句inner join、
System.out.println("数据库中的工人姓名:"+worker.getName()); //共有属性
System.out.println("数据库中的工人工号:"+worker.getWno()); //特征属性
System.out.println("数据库中的工人工资:"+worker.getSalary());//特征属性
session.getTransaction().commit();
} catch (Exception e) {
session.getTransaction().rollback();
System.out.print("数据库查询失败");
e.printStackTrace();
}finally{
HibernateUtil.closeSession();
}
}
测试结果:
Hibernate:
select
student0_.sid as id1_5_0_,
student0_1_.name as name2_5_0_,
student0_1_.sex as sex3_5_0_,
student0_1_.age as age4_5_0_,
student0_.sno as sno2_7_0_,
student0_.school as school3_7_0_
from
tb_student student0_
inner join
tb_persons student0_1_
on student0_.sid=student0_1_.id
where
student0_.sid=?
数据库中的学生姓名:张三
数据库中的学生学号:100120122016
数据库中的学生学校:华中科技大学
Hibernate:
select
worker0_.wid as id1_5_0_,
worker0_1_.name as name2_5_0_,
worker0_1_.sex as sex3_5_0_,
worker0_1_.age as age4_5_0_,
worker0_.wno as wno2_10_0_,
worker0_.salary as salary3_10_0_
from
tb_worker worker0_
inner join
tb_persons worker0_1_
on worker0_.wid=worker0_1_.id
where
worker0_.wid=?
数据库中的工人姓名:李四
数据库中的工人工号:W20121224
数据库中的工人工资:8000