【7.6.2】基于一张表的继承映射
1.子类和父类的关系图:
2.Person,Student和Teacher类
package cn.siggy.pojo;
public class Person {
private int id;
private String name;
private int age;
/*get/set*/
}
------------------------------------------------------------------
package cn.siggy.pojo;
public class Student extends Person{
private String work;
public String getWork() {
return work;
}
public void setWork(String work) {
this.work = work;
}
}
-------------------------------------------------------------------
package cn.siggy.pojo;
public class Teacher extends Person{
private int salary;
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
}
3.映射文件
Person.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="cn.siggy.pojo"> <class name="Person"> <id name="id" column="id"> <generator class="native"></generator> </id> <!-- 指明鉴别器 --> <discriminator column="type" type="string"/> <property name="name"/> <property name="age"/> </class> <subclass name="Student" discriminator-value="s" extends="Person"> <property name="work"/> </subclass> <subclass name="Teacher" discriminator-value="t" extends="Person"> <property name="salary"/> </subclass> </hibernate-mapping>
映射文件理解:
<!-- 指明鉴别器 -->
<discriminator column="type" type="string"/>
4.测试代码
package cn.siggy.test;
import java.sql.SQLException;
import javax.sql.rowset.serial.SerialException;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.junit.Test;
import cn.siggy.pojo.Person;
import cn.siggy.pojo.Student;
import cn.siggy.pojo.Teacher;
import cn.siggy.util.HibernateUtil;
public class HibernateTest {
@Test
public void testCreateDB(){
Configuration cfg = new Configuration().configure();
SchemaExport se = new SchemaExport(cfg);
//第一个参数 是否生成ddl脚本 第二个参数 是否执行到数据库中
se.create(true, true);
}
@Test
public void testSave() throws HibernateException, SerialException, SQLException{
Configuration cfg = new Configuration().configure();
SessionFactory factory = cfg.buildSessionFactory(new StandardServiceRegistryBuilder()
.applySettings(cfg.getProperties()).build());
Session session = null;
Transaction tx = null;
try{
session = factory.openSession();
tx = session.beginTransaction();
Teacher teacher = new Teacher();
teacher.setName("siggy");
teacher.setAge(26);
teacher.setSalary(5000);
Student student = new Student();
student.setName("小明");
student.setAge(22);
student.setWork("hello world");
Student student1 = new Student();
student1.setName("小强");
student1.setAge(20);
student1.setWork("struts2");
session.save(student);
session.save(student1);
session.save(teacher);
tx.commit();
}catch (HibernateException e) {
if(tx!=null)
tx.rollback();
e.printStackTrace();
throw e;
}finally{
HibernateUtil.closeSession();
}
}
@Test
public void testGet(){
Session session = null;
Transaction tx = null;
try{
session = HibernateUtil.getSession();
tx = session.beginTransaction();
Person person = (Person)session.get(Person.class, 2);
System.out.println(person.getName());
if(person instanceof Student){
Student stu = (Student)person;
System.out.println(stu.getWork());
}
tx.commit();
}catch (HibernateException e) {
if(tx!=null)
tx.rollback();
e.printStackTrace();
throw e;
}finally{
HibernateUtil.closeSession();
}
}
@Test
public void testLoad(){
Session session = null;
Transaction tx = null;
try{
session = HibernateUtil.getSession();
tx = session.beginTransaction();
Person person = (Person)session.load(Person.class, 2);
System.out.println(person.getName());
if(person instanceof Student){
Student stu = (Student)person;
System.out.println(stu.getWork());
}
tx.commit();
}catch (HibernateException e) {
if(tx!=null)
tx.rollback();
e.printStackTrace();
throw e;
}finally{
HibernateUtil.closeSession();
}
}
}
5.测试结果
1.执行testSave()方法:
2.执行testGet()方法:【hibernate是通过鉴别器(即type字段)来判断对象是Student还Teacher的】
3.执行testLoad()方法:
【会出现类型转换错误,因为Load方式要在对象被使用时才加载,而加载前是一个动态代理类型,故而hibernate不知道它是Person或者Student还是Teacher】
备注:测试代码是可以运行的,因为运行一下代码时:
@Test public void testLoad(){ Session session = null; Transaction tx = null; try{ session = HibernateUtil.getSession(); tx = session.beginTransaction(); Person person = (Person)session.load(Person.class, 2); System.out.println(person.getName()); if(person instanceof Student){ Student stu = (Student)person; System.out.println(stu.getWork()); } tx.commit(); }catch (HibernateException e) { if(tx!=null) tx.rollback(); e.printStackTrace(); throw e; }finally{ HibernateUtil.closeSession(); } }System.out.println(person.getName());便已经使用了Person对象,故而Load开始加载Person表中的信息,再根据type字段,从而可以判断Person是Student还是Teacher对象
总结:
1、在单表继承映射中,hibernate通过鉴别器来识别之类的类型。鉴别器由hibernate来进行维护。
2、查询数据时,如果使用get查询得到的数据类型可以进行多态判断。如果是通过load(lazy)查询,不能判断。




浙公网安备 33010602011771号