前两篇文章《
Eclipse快速上手Hibernate--4. 继承映射(1)<script language="javascript" type="text/javascript"> document.title="Eclipse快速上手Hibernate--4. 继承映射(1) - "+document.title </script> 》和《
继承映射(2
)》中已经谈了每个类层次结构一个表(table per class hierarchy)与每个子类一个表(table per subclass)的策略,这篇文章主要说的是每个具体类一个表(table per concrete class)。一些重复的部分这里就不说了,请参考前两篇文章。
● 缺点:
· 类的修改会导致相对应的表及其子类所对应表的更改。
· 当含有多重子类时,会造成在数据库表格中生成重复的字段。
这个策略很简单,抽象的基类不参与映射,具体子类参与映射。
1. 创建项目
· 继续沿用上篇文章中所建的Java项目:InheritanceMapping。
2. 编写类文件
· 新建一个类,包名:javamxj.inheritance.two,类名:Person。然后在生成的代码中添加变量,再利用“生成 Getter 和 Setter”,具体方式同《
Eclipse快速上手Hibernate--1. 入门实例 》文章中的编辑User.java的方式一样。
· 这个类是父类,要注意,这里并没有将父类映射成表。
Person.java
/* * Hibernate - 继承映射(每个具体类一个表) * 创建日期 2005-4-9 * @author javamxj(分享java快乐) * @link Blog: htpp://javamxj.mblogger.cn * htpp://blog.csdn.net/javamxj/ */ package javamxj.inheritance.three; public abstract class Person { private Long id; private String name; /** * @hibernate.id * column="ID" * generator-class="hilo" * unsaved-value="null" */ public Long getId() { return id; } public void setId(Long id) { this.id = id; } /** * @hibernate.property * length = "24" */ public String getName() { return name; } public void setName(String name) { this.name = name; } }
· 子类Student.java
Student.java
|
package javamxj.inheritance.three; /** * @hibernate.class * table="Student" */ public class Student extends Person { private String studentNumber; /** * @hibernate.property * length = "24" */ public String getStudentNumber() { return studentNumber; } public void setStudentNumber(String studentNumber) { this.studentNumber = studentNumber; } } |
· 子类Professor.java
Professor.java
|
package javamxj.inheritance.three; /** * @hibernate.class * table="Professor" */ public class Professor extends Person { private int salary; /** * @hibernate.property */ public int getSalary() { return salary; } public void setSalary(int salary) { this.salary = salary; } } |
· 这两个子类都很简单,跟平常的写法相同,只是简单的映射成一个表。
· 好了,这时整个项目的结构如下:
3. 运行任务
· 双击“generate-hbm”任务,会发现在包中多了Professor.hbm.xml和Student.hbm.xml两个文件。如果没有,按F5键刷新一下(这里建议打开Eclipse的“首选项”对话框,在“工作台”中勾选“自动刷新工作空间”和“在构建之前自动保存”这两项,这样以后不用每次都刷新了)。
· 这是通过两个子类所生成的映射文件,注意没有生成父类的映射文件,而且这两个子类的映射文件都已经包含了父类的属性。
Professor.hbm.xml
<?xml version="1.0" encoding="GBK"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"> <hibernate-mapping > <class name="javamxj.inheritance.three.Professor" table="Professor" dynamic-update="false" dynamic-insert="false" select-before-update="false" optimistic-lock="version" > <id name="id" column="ID" type="java.lang.Long" unsaved-value="null" > <generator class="hilo"> <!-- To add non XDoclet generator parameters, create a file named hibernate-generator-params-Professor.xml containing the additional parameters and place it in your merge dir. --> </generator> </id> <property name="salary" type="int" update="true" insert="true" access="property" column="salary" /> <property name="name" type="java.lang.String" update="true" insert="true" access="property" column="name" length="24" /> <!-- To add non XDoclet property mappings, create a file named hibernate-properties-Professor.xml containing the additional properties and place it in your merge dir. --> </class> </hibernate-mapping>
Student.hbm.xml
<?xml version="1.0" encoding="GBK"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"> <hibernate-mapping > <class name="javamxj.inheritance.three.Student" table="Student" dynamic-update="false" dynamic-insert="false" select-before-update="false" optimistic-lock="version" > <id name="id" column="ID" type="java.lang.Long" unsaved-value="null" > <generator class="hilo"> <!-- To add non XDoclet generator parameters, create a file named hibernate-generator-params-Student.xml containing the additional parameters and place it in your merge dir. --> </generator> </id> <property name="studentNumber" type="java.lang.String" update="true" insert="true" access="property" column="studentNumber" length="24" /> <property name="name" type="java.lang.String" update="true" insert="true" access="property" column="name" length="24" /> <!-- To add non XDoclet property mappings, create a file named hibernate-properties-Student.xml containing the additional properties and place it in your merge dir. --> </class> </hibernate-mapping>
· 同时在hibernate.cfg.xml文件中会自动添加这两个映射文件信息:
<mapping resource="javamxj/inheritance/three/Professor.hbm.xml"/>
<mapping resource="javamxj/inheritance/three/Student.hbm.xml"/>
<mapping resource="javamxj/inheritance/three/Student.hbm.xml"/>
· 先运行MySQL,然后双击“schemaexport”任务,在项目根目录下,会更新“schema-export.sql”文件。
打开这个文件,会发现添加了以下一些语句。
create table Student (
ID bigint not null,
studentNumber varchar(24),
name varchar(24),
primary key (ID)
)
ID bigint not null,
studentNumber varchar(24),
name varchar(24),
primary key (ID)
)
create table Professor (
ID bigint not null,
salary integer,
name varchar(24),
primary key (ID)
)
ID bigint not null,
salary integer,
name varchar(24),
primary key (ID)
)
· 切换到数据库中,会发现已经自动产生了数据表Student、Professor。
4. 测试程序
· 好了,在包javamxj.inheritance.two下新建一个Demo.java类,很简单,前半部分是添加数据,后半部分是简单的测试。
Demo.java
/* * Hibernate - 继承映射(每个具体类一个表) * 创建日期 2005-4-9 * @author javamxj(分享java快乐) * @link Blog: htpp://javamxj.mblogger.cn * htpp://blog.csdn.net/javamxj/ */ package javamxj.inheritance.three; import java.util.Iterator; import java.util.List; import net.sf.hibernate.HibernateException; import net.sf.hibernate.Session; import net.sf.hibernate.SessionFactory; import net.sf.hibernate.Transaction; import net.sf.hibernate.cfg.Configuration; public class Demo { public static void main(String[] args) { try { new Demo(); } catch (HibernateException he) { he.printStackTrace(); } } public Demo() throws HibernateException { SessionFactory sf = new Configuration().configure() .buildSessionFactory(); Session sess = sf.openSession(); Transaction tx = null; try { tx = sess.beginTransaction(); Student student = new Student(); student.setName("张三"); student.setStudentNumber("1234554321"); sess.save(student); Professor professor = new Professor(); professor.setName("李四"); professor.setSalary(4300); sess.save(professor); tx.commit(); } catch (HibernateException e) { if (tx != null) tx.rollback(); throw e; } finally { sess.close(); } sess = sf.openSession(); tx = null; try { tx = sess.beginTransaction(); List person = sess.find("from " + Person.class.getName()); for (Iterator it = person.iterator(); it.hasNext();) { Person p = (Person) it.next(); System.out.println("人员 '" + p.getName() + "' its class is: " + p.getClass().getName()); } tx.commit(); } catch (HibernateException e) { if (tx != null) tx.rollback(); throw e; } finally { sess.close(); } } }
· 运行这个类,控制台输出如下:
· 同时,数据表中生成如下数据:
小结:
● 优点:
· 报表操作实现简单:表中包含了具体子类的所有信息。
· 报表操作实现简单:表中包含了具体子类的所有信息。
● 缺点:
· 类的修改会导致相对应的表及其子类所对应表的更改。
· 当含有多重子类时,会造成在数据库表格中生成重复的字段。
参考:
· HIBERNATE - 符合Java习惯的关系数据库持久化(第8章)
下篇文章说说组件(Component)映射。