对于“每个具体类一张表”的映射策略,可以采用两种方式。第一种方式是使用<union-subclass>。另一种方法时采用隐式多态。
以上一篇博客《hibernate单表继承映射》所述案列为例,我们主要学习第一种方式。
与上篇文章不同的Person.hbm.xml配置文件
<hibernate-mapping package="com.test.pojo">
<!-- abstract="true":指明Person类是抽象的,不生成对应的person数据库表 -->
<class name="Person" abstract="true">
<id name="id">
<!-- assigned:自己指定主键 -->
<generator class="assigned"></generator>
</id>
<property name="name" />
<property name="age" />
<union-subclass name="Student">
<property name="work" />
</union-subclass>
<union-subclass name="Teacher">
<property name="salary" />
</union-subclass>
</class>
</hibernate-mapping>
测试类:
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 save(){
Session session=null;
Transaction tx=null;
try{
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Teacher teacher=new Teacher();
teacher.setId(1);
teacher.setName("teacher");
teacher.setAge(20);
teacher.setSalary(5000);
Student student=new Student();
student.setId(2);
student.setName("stu1");
student.setAge(20);
student.setWork("hello world");
Student stu=new Student();
stu.setId(3);
stu.setName("stu2");
stu.setAge(21);
stu.setWork("Struts2");
session.save(student);
session.save(stu);
session.save(teacher);
tx.commit();
}catch(Exception e){
if(tx!=null)
tx.rollback();
e.printStackTrace();
}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(Exception e){
tx.rollback();
e.printStackTrace();
}finally{
HibernateUtil.closeSession();
}
}
}
首先执行testCreateDB,打印信息如下:
drop table if exists Student
drop table if exists Teacher
create table Student (
id integer not null,
name varchar(255),
age integer,
work varchar(255),
primary key (id)
)
create table Teacher (
id integer not null,
name varchar(255),
age integer,
salary integer,
primary key (id)
)
数据库表信息如图:
执行save代码,打印sql语句如下:
Hibernate:
insert
into
Student
(name, age, work, id)
values
(?, ?, ?, ?)
Hibernate:
insert
into
Student
(name, age, work, id)
values
(?, ?, ?, ?)
Hibernate:
insert
into
Teacher
(name, age, salary, id)
values
(?, ?, ?, ?)
数据库表信息如下:
总结:
1、在每个具体类一张表的继承映射中,主键的生成不能使用identity。建议使用uuid,sequence,assigned等。
2、数据库表的结构更加合理。多态查询效率不高。