[标题]:[原]Hibernate继承映射-具体类映射为数据库表
[时间]:2009-6-21
[摘要]:每一个具体子类映射成单个数据库表,而抽象基类不参与映射。优点:数据操作实现简单,每个表中都包含自己所需要的具体子类的所有信息,减少了多表关联操作时的性能消耗。缺点:类的修改会导致相对应的表及其子类所对应表的更改。不支持多态查询。应用:适合在类层次结构上有一定数量的抽象类的情况下使用。
[关键字]:Hibernate,ORM,关联,继承,持久化,映射,Abstract
[环境]:MyEclipse7,Hibernate3.2,MySQL5.1
[作者]:Winty (wintys@gmail.com) http://www.blogjava.net/wintys
[正文]:
每一个具体子类映射成单个数据库表,而抽象基类不参与映射。
优点:数据操作实现简单,每个表中都包含自己所需要的具体子类的所有信息,减少了多表关联操作时的性能消耗。
缺点:
类的修改会导致相对应的表及其子类所对应表的更改。不支持多态查询。
应用:
适合在类层次结构上有一定数量的抽象类的情况下使用。
例:学校管理系统中的实体关系:
![](http://dl.iteye.com/upload/attachment/153598/e66d239b-a2bb-3dd6-920f-2fd10fd5b352.jpg)
【图:department.jpg】
1、概述
a.实体类
public class Department {
......
//由于Person类没有被映射,所以无法实现Department到Person的关联
......
}
public abstract class Person {
......
private Department department;
......
}
public class Student extends Person {
......
}
public class Teacher extends Person {
......
}
b.数据库表
具体子类Student和Teacher分别映射成一张表,各自的表中都包含从父类继承来的属性。
c.配置文件
由于Person类没有被映射,所以无法映射Person到Department的关联,只能由子类Student和Teacher实现映射。
Student.hbm.xml:
包含父类属性的映射
......
<many-to-one name="department"
unique="true"
column="dept"
class="wintys.hibernate.inheritance.concrete.Department"/>
......
Teacher.hbm.xml:
包含父类属性的映射
......
<many-to-one name="department"
unique="true"
column="dept"
class="wintys.hibernate.inheritance.concrete.Department"/>
......
2、实体类:
Department.java:
/**
*
* @version 2009-06-20
* @author Winty (wintys@gmail.com)
*
*/
public class Department {
private Integer id;
private String name;
private String desc;
public Department(){
}
public Department(String name , String desc){
this.name = name;
this.desc = desc;
}
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 String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
Person.java:
/**
*
* @version 2009-06-20
* @author Winty (wintys@gmail.com)
*
*/
public abstract class Person {
private Integer id;
private String name;
private Department department;
public Person(){
}
public Person(String name){
this.name = name;
}
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 Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
}
Student.java:
/**
*
* @version 2009-06-20
* @author Winty (wintys@gmail.com)
*
*/
public class Student extends Person {
private String studentMajor;
public Student(){
}
public Student(String name , String major){
super(name);
this.studentMajor = major;
}
public String getStudentMajor() {
return studentMajor;
}
public void setStudentMajor(String studentMajor) {
this.studentMajor = studentMajor;
}
}
Teacher.java:
/**
*
* @version 2009-06-20
* @author Winty (wintys@gmail.com)
*
*/
public class Teacher extends Person {
private Float teacherSalary;
public Teacher(){
}
public Teacher(String name , Float teacherSalary){
super(name);
this.teacherSalary = teacherSalary;
}
public Float getTeacherSalary() {
return teacherSalary;
}
public void setTeacherSalary(Float teacherSalary) {
this.teacherSalary = teacherSalary;
}
}
3、数据库表:
![](http://dl.iteye.com/upload/attachment/153594/84edb1b4-417b-34de-9772-17f577c47b71.jpg)
【图:concret_db.jpg】
db.sql:
-- Date:2009-06-20
-- http://www.blogjava.net/wintys
-- Department
CREATE TABLE mydepartment(
id INT(4) NOT NULL,
name VARCHAR(100),
descs VARCHAR(100),
PRIMARY KEY(id)
);
-- Student
CREATE TABLE mystudent(
id INT(4) NOT NULL,
name VARCHAR(100),
dept INT(4),-- 从Person继承了与Department的关联
studentMajor VARCHAR(100),
PRIMARY KEY(id),
CONSTRAINT FK_dept_s FOREIGN KEY(dept) REFERENCES mydepartment(id)
);
-- Teacher
CREATE TABLE myteacher(
id INT(4) NOT NULL,
name VARCHAR(100),
dept INT(4), -- 从Person继承了与Department的关联
teacherSalary FLOAT(7,2),
PRIMARY KEY(id),
CONSTRAINT FK_dept_t FOREIGN KEY(dept) REFERENCES mydepartment(id)
);
4、映射文件:
![](http://dl.iteye.com/upload/attachment/153596/72d0e4d3-29a5-3c83-ae9b-b7ac9b7a5b9f.jpg)
【图:concrete_mapping.jpg】
Department.hbm.xml:
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="wintys.hibernate.inheritance.concrete.Department" table="mydepartment" catalog="db">
<id name="id" type="int">
<column name="id" not-null="true"/>
<generator class="increment" />
</id>
<property name="name" />
<property name="desc" type="string" column="descs"/>
</class>
</hibernate-mapping>
Student.hbm.xml:
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="wintys.hibernate.inheritance.concrete.Student" table="mystudent" catalog="db">
<id name="id" type="int">
<column name="id" not-null="true"/>
<generator class="increment" />
</id>
<property name="name" />
<property name="studentMajor" />
<many-to-one name="department"
unique="true"
column="dept"
class="wintys.hibernate.inheritance.concrete.Department"/>
</class>
</hibernate-mapping>
Teacher.hbm.xml:
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="wintys.hibernate.inheritance.concrete.Teacher" table="myteacher" catalog="db">
<id name="id" type="int">
<column name="id" not-null="true"/>
<generator class="increment" />
</id>
<property name="name" />
<property name="teacherSalary" type="float"/>
<many-to-one name="department"
unique="true"
column="dept"
class="wintys.hibernate.inheritance.concrete.Department"/>
</class>
</hibernate-mapping>
hibernate.cfg.xml:
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<!-- Generated by MyEclipse Hibernate Tools. -->
<hibernate-configuration>
<session-factory>
<property name="connection.username">root</property>
<property name="connection.url">
jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=utf-8
</property>
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="myeclipse.connection.profile">MySQLDriver</property>
<property name="connection.password">root</property>
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="show_sql">true</property>
<mapping
resource="wintys/hibernate/inheritance/concrete/Department.hbm.xml" />
<mapping
resource="wintys/hibernate/inheritance/concrete/Student.hbm.xml" />
<mapping
resource="wintys/hibernate/inheritance/concrete/Teacher.hbm.xml" />
</session-factory>
</hibernate-configuration>
4、使用测试:
DAO.java:
import java.util.List;
public interface DAO {
public void insert();
public <T> List<T> select(String hql);
}
DAOBean.java:
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
/**
*
* @version 2009-06-20
* @author Winty (wintys@gmail.com)
*
*/
public class DAOBean implements DAO {
@Override
public void insert() {
Transaction tc = null;
try{
Department dept = new Department("college of math" , "the top 3 college");
Person p1,p2;
p1 = new Student("Sam" , "Math");
p1.setDepartment(dept);
p2 = new Teacher("Martin" , new Float(15000f));
p2.setDepartment(dept);
Session session = HibernateUtil.getSession();
tc = session.beginTransaction();
session.save(dept);
//多态保存
session.save(p1);
session.save(p2);
tc.commit();
}catch(HibernateException e){
try{
if(tc != null)
tc.rollback();
}catch(Exception ex){
System.err.println(ex.getMessage());
}
System.err.println(e.getMessage());
}finally{
HibernateUtil.closeSession();
}
}
@SuppressWarnings("unchecked")
@Override
public <T> List<T> select(String hql) {
List<T> items = null;
Transaction tc = null;
try{
Session session = HibernateUtil.getSession();
tc = session.beginTransaction();
Query query = session.createQuery(hql);
items = query.list();
tc.commit();
}catch(HibernateException e){
try{
if(tc != null){
tc.rollback();
items = null;
}
}catch(Exception ex){
System.err.println(ex.getMessage());
}
System.err.println(e.getMessage());
}finally{
//HibernateUtil.closeSession();
}
return items;
}
}
HibernateUtil.java:
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
* Hibernate Session管理
* @author Winty
*/
public class HibernateUtil {
private static SessionFactory factory = null;
private static ThreadLocal<Session> threadLocal;
static {
threadLocal = new ThreadLocal<Session>();
}
private HibernateUtil(){
}
//Should be call only once.
//设置Hibernate.cfg.xml的位置
public static void setConfigFile(String hibernate_cfg_xml){
try{
factory = new Configuration()
.configure(hibernate_cfg_xml)
.buildSessionFactory();
}catch(HibernateException e){
System.err.println(e.getMessage());
}
}
public static Session getSession()throws HibernateException{
Session session = threadLocal.get();
if(session == null){
session = factory.openSession();
threadLocal.set(session);
}
return session;
}
public static void closeSession()throws HibernateException{
Session session = threadLocal.get();
if(session != null){
session.close();
}
threadLocal.set(null);
}
}
Test.java:
import java.util.Iterator;
import java.util.List;
public class Test {
public static void main(String[] args) {
String config = "wintys/hibernate/inheritance/concrete/hibernate.cfg.xml";
HibernateUtil.setConfigFile(config);
DAO dao = new DAOBean();
dao.insert();
//不支持多态查询
//Error:Person is not mapped
//List<Person> ps = dao.select("from Person");
//System.out.println(printStudentOrTeacher(ps));
List<Student> students = dao.select("from Student");
System.out.println(printStudentOrTeacher(students));
List<Student> teachers = dao.select("from Teacher");
System.out.println(printStudentOrTeacher(teachers));
}
public static String printStudentOrTeacher(List<? extends Person> students){
String str = "";
Iterator<? extends Person> it = students.iterator();
while(it.hasNext()){
Person person = it.next();
int id = person.getId();
String name = person.getName();
Department dept = person.getDepartment();
int deptId = dept.getId();
String deptName = dept.getName();
String deptDesc = dept.getDesc();
str += "id:" +id + ""n";
str += "name:" + name + ""n";
if(person instanceof Student)
str += "major:" + ((Student) person).getStudentMajor() + ""n";
if(person instanceof Teacher)
str += "salary:" + ((Teacher) person).getTeacherSalary().toString() + ""n";
str += "dept:" + ""n";
str += " deptId:" + deptId + ""n";
str += " deptName:" + deptName + ""n";
str += " deptDesc:" + deptDesc + ""n";
str += ""n";
}
return str;
}
}
5、运行结果
控制台显示:
Hibernate: select max(id) from mydepartment
Hibernate: select max(id) from mystudent
Hibernate: select max(id) from myteacher
Hibernate: insert into db.mydepartment (name, descs, id) values (?, ?, ?)
Hibernate: insert into db.mystudent (name, studentMajor, dept, id) values (?, ?, ?, ?)
Hibernate: insert into db.myteacher (name, teacherSalary, dept, id) values (?, ?, ?, ?)
Hibernate: select student0_.id as id1_, student0_.name as name1_, student0_.studentMajor as studentM3_1_, student0_.dept as dept1_ from db.mystudent student0_
Hibernate: select department0_.id as id0_0_, department0_.name as name0_0_, department0_.descs as descs0_0_ from db.mydepartment department0_ where department0_.id=?
id:1
name:Sam
major:Math
dept:
deptId:1
deptName:college of math
deptDesc:the top 3 college
Hibernate: select teacher0_.id as id2_, teacher0_.name as name2_, teacher0_.teacherSalary as teacherS3_2_, teacher0_.dept as dept2_ from db.myteacher teacher0_
id:1
name:Martin
salary:15000.0
dept:
deptId:1
deptName:college of math
deptDesc:the top 3 college
[参考资料]:
《J2EE项目实训--Hibernate框架技术》-杨少波 : 清华大学出版社
作者:Winty (wintys@gmail.com)
博客:http://www.blogjava.net/wintys