Eclipse快速上手Hibernate--4. 继承映射(1)

继承

   前面的《Eclipse快速上手Hibernate--1. 入门实例 》等三篇文章已经谈了Hibernate的入门以及利用工具创建的方法。这篇文章主要说说在Hibernate中的继承映射。相关配置请参考前三篇文章。    如果程序中的对象含有继承的关系,在Hibernate中有以下三种策略将这种关系映射到数据表上:· 每个类层次结构一个表(table per class hierarchy)· 每个子类一个表(table per subclass) · 每个具体类一个表(table per concrete class)(有一些限制)    每个类层次结构一个表的方式是将所有继承同一父类别的对象储存在同一个表格中,为了做到这一点,需要在表格中使用识别字段来表示某一列(row)是属于某个子类别或父类别,在这个主题中我们将先说明这个方法。 1. 创建项目 ·  新建一个Java项目:InheritanceMapping,注意选中“创建单独的源文件夹和输出文件夹”,同时添加“用户库”:hibernate。   2. 编写类文件 ·  新建一个类,包名:javamxj.inheritance.one,类名:Animal。然后在生成的代码中添加变量,再利用“生成 Getter 和 Setter”,具体方式同《Eclipse快速上手Hibernate--1. 入门实例 》文章中的编辑User.java的方式一样。
Animal.java

/* * Hibernate - 继承映射(每个类层次一个表) * 创建日期 2005-4-9 * @author javamxj(分享java快乐) * @link Blog: htpp://javamxj.mblogger.cn * htpp://blog.csdn.net/javamxj/ */package javamxj.inheritance.one;/** * @hibernate.class * table="Animal" * discriminator-value="Animal" * @hibernate.discriminator * column="ANIMAL_TYPE" * type="string" * length = "10" */public abstract class Animal {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;}public abstract void makeSound();}

 ·  这个类是父类,值得注意是在类层次标记中添加了一个discriminator标记,并用它定义了一个字段“ANIMAL_TYPE”,这个字段就是用来识别某一列(row)是属于某个子类别或父类别的。  ·  子类Cat.javaCat.java
package javamxj.inheritance.one;/** * @hibernate.subclass * discriminator-value="Cat" */public class Cat extends Animal {private String FurColor;public void makeSound() {System.out.println("喵喵");}/** * @hibernate.property * length = "24" */public String getFurColor() {return FurColor;}public void setFurColor(String furColor) {FurColor = furColor;}}
 ·  子类Dog.javaDog.java
package javamxj.inheritance.one;/** * @hibernate.subclass * discriminator-value="Dog" */public class Dog extends Animal {private String category;public void makeSound() {System.out.println("汪汪");}/** * @hibernate.property * length = "24" */public String getCategory() {return category;}public void setCategory(String category) {this.category = category;}}
·  这两个子类都很简单,注意添加的hibernate.subclass的标记,指定其识别字段。  3. 构建文件Build.xml ·  在项目根目录下建立一个build.xml,要注意的是环境变量和数据库的设置要符合自己的实际配置,这里库文件目录的设置是"D:/java/Hibernate/lib",参考文章《Eclipse快速上手Hibernate--1. 入门实例》中的设置。·  在MySQL中需要先建立一个HibernateTest数据库,为了解决中文问题,使用了GBK编码,注意“&”,这是由于XDoclet生成Hibernate配置文件时,会丢失一个“amp;”字符串(一个小Bug)。·  这里我用build.xml中的“hibernatedoclet”任务直接生成“hibernate.cfg.xml”配置文件。
build.xml

<?xml version="1.0" encoding="GBK"?><project name="Hibernate中的继承映射" default="help" basedir="."><!-- ****** 环境设置,可以根据自己的实际配置自行更改 ***** --><!-- 源文件目录, 可以通过 项目->属性->Java构建路径 更改 --><property name="src.dir" value="./src" /><!-- 输出的class文件目录,可以通过 项目->属性->Java构建路径 更改 --><property name="class.dir" value="./bin" /><!-- 库文件目录 --><property name="lib.dir" value="D:/java/Hibernate/lib" /><!-- ****** 数据库设置,可以根据自己的实际配置自行更改 ***** --><property name="hibernate.dialect" value="net.sf.hibernate.dialect.MySQLDialect"></property><property name="hibernate.driver" value="com.mysql.jdbc.Driver"></property><!-- & --><property name="hibernate.jdbc.url" value="jdbc:mysql://localhost:3306/HibernateTest?useUnicode=true&characterEncoding=GBK"></property><property name="hibernate.username" value="root"></property><property name="hibernate.password" value="javamxj"></property><property name="hibernate.show.sql" value="true"></property><!-- 定义类路径 --><path id="project.class.path"><fileset dir="${lib.dir}"><include name="*.jar"/></fileset><pathelement location="${class.dir}" /></path><!-- ************************************************************** --><!-- 使用说明 --><!-- ************************************************************** --><target name="help"><echo message="利用工具开发Hibernate" /><echo message="-----------------------------------" /><echo message="" /><echo message="提供以下任务:" /><echo message="" /><echo message="generate-hbm --> 运行HibernateDoclet,生成 Hibernate 类的映射文件" /><echo message="schemaexportt --> 运行SchemaExport,利用 hbm.xml 文件生成数据表" /><echo message="" /></target><!-- ************************************************************** --><!-- HibernateDoclet 任务 --><!-- ************************************************************** --><target name="generate-hbm" ><echo message="运行HibernateDoclet,生成 Hibernate 类的映射文件"/><taskdef name="hibernatedoclet" classname="xdoclet.modules.hibernate.HibernateDocletTask" classpathref="project.class.path"></taskdef><hibernatedoclet destdir="${src.dir}" excludedtags="@version,@author,@todo" force="true" encoding="GBK" verbose="true"><fileset dir="${src.dir}"><include name="**/*.java"/></fileset><hibernate version="2.0" xmlencoding="GBK" /><!-- 生成配置文件 --><hibernatecfgdialect="${hibernate.dialect}"driver="${hibernate.driver}" jdbcUrl="${hibernate.jdbc.url}" userName="${hibernate.username}" password="${hibernate.password}"showSql="${hibernate.show.sql}"xmlencoding="GBK"/></hibernatedoclet></target><!-- ************************************************************** --><!-- SchemaExport 任务 --><!-- ************************************************************** --><target name="schemaexport"><echo message="运行SchemaExport,利用 hbm.xml 文件生成数据表"/><taskdef name="schemaexport" classname="net.sf.hibernate.tool.hbm2ddl.SchemaExportTask" classpathref="project.class.path"></taskdef><schemaexport config="${src.dir}/hibernate.cfg.xml" quiet="no" text="no" drop="no" output="schema-export.sql"></schemaexport></target></project>
 
 · 好了,只要这四个文件就够了,其它的会自动生成的。整个项目的结构如下:   4. 运行任务 ·  双击“generate-hbm”任务,会发现在包中多了一个Animal.hbm.xml文件,在src目录下会多了一个hibernate.cfg.xml文件,如果没有,按F5键刷新一下(这里建议打开Eclipse的“首选项”对话框,在“工作台”中勾选“自动刷新工作空间”和“在构建之前自动保存”这两项,这样以后不用每次都刷新了)。
Animal.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.one.Animal" table="Animal" dynamic-update="false" dynamic-insert="false" select-before-update="false" optimistic-lock="version" discriminator-value="Animal" > <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-Animal.xml containing the additional parameters and place it in your merge dir. --> </generator> </id> <discriminator column="ANIMAL_TYPE" type="string" length="10" /> <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-Animal.xml containing the additional properties and place it in your merge dir. --> <subclass name="javamxj.inheritance.one.Cat" dynamic-update="false" dynamic-insert="false" discriminator-value="Cat" > <property name="furColor" type="java.lang.String" update="true" insert="true" access="property" column="furColor" length="24" /> <!-- To add non XDoclet property mappings, create a file named hibernate-properties-Cat.xmlcontaining the additional properties and place it in your merge dir. --> </subclass> <subclass name="javamxj.inheritance.one.Dog" dynamic-update="false" dynamic-insert="false" discriminator-value="Dog" > <property name="category" type="java.lang.String" update="true" insert="true" access="property" column="category" length="24" /> <!-- To add non XDoclet property mappings, create a file named hibernate-properties-Dog.xmlcontaining the additional properties and place it in your merge dir. --> </subclass> </class></hibernate-mapping>
 
 hibernate.cfg.xml
<?xml version="1.0" encoding="GBK"?><!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 2.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd"><!-- Generated file - Do not edit! --><hibernate-configuration><!-- a SessionFactory instance listed as /jndi/name --><session-factory><!-- properties --><property name="dialect">net.sf.hibernate.dialect.MySQLDialect</property><property name="show_sql">true</property><property name="use_outer_join">false</property><property name="connection.username">root</property><property name="connection.password">javamxj</property><property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://localhost:3306/HibernateTest?useUnicode=true&characterEncoding=GBK</property><!-- mapping files --><mapping resource="javamxj/inheritance/one/Animal.hbm.xml"/></session-factory></hibernate-configuration>
 ·  双击“schemaexport”任务,在项目根目录下,会产生一个“schema-export.sql”文件。schema-export.sqldrop table if exists Animaldrop table if exists hibernate_unique_keycreate table Animal (   ID bigint not null,   ANIMAL_TYPE varchar(10) not null,   name varchar(24),   furColor varchar(24),   category varchar(24),   primary key (ID))create table hibernate_unique_key (    next_hi integer )insert into hibernate_unique_key values ( 0 ) ·  切换到数据库中,会发现已经自动产生了数据表animal(表hibernate_unique_key是由于采用hilo主键策略生成的)。  5. 测试程序 ·  好了,在包javamxj.inheritance.one下新建一个Demo.java类,很简单,前半部分是添加数据,后半部分是简单的测试。
Demo.java

package javamxj.inheritance.one;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();Cat cat = new Cat();cat.setName("小白");cat.setFurColor("白色");sess.save(cat);Dog dog = new Dog();dog.setName("小黑");dog.setCategory("京巴狗");sess.save(dog);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 animals = sess.find("from " + Animal.class.getName());for (Iterator it = animals.iterator(); it.hasNext();) {Animal animal = (Animal) it.next();System.out.println("动物 '" + animal.getName()+ "' 所在类是: " + animal.getClass().getName());System.out.print("发出叫声: ");animal.makeSound();}tx.commit();} catch (HibernateException e) {if (tx != null)tx.rollback();throw e;} finally {sess.close();}}}
 
 ·  运行这个类,控制台输出如下: ·  同时,数据表中生成如下数据:注意其中为“NULL”的部分。 ·  最后的项目结构如下:  小结:  ● 优点:· 实现简单。· 支持多态——对象角色发生变化,或存在多重角色时。· 报表操作实现简单:表中包含了所有信息。● 缺点:· 增加类层次中的耦合。类层次中任何类的属性的增加都会导致表的变更;某个子类属性的修改会影响到整个层次结构,而不仅仅是该子类。· 浪费了一些数据库空间。浪费空间的多少取决于继承层次的深度。层次越深,不同的属性越多,属性的全集就越大,也就越浪费空间。· 可能需要指明具体的角色。  参考:· HIBERNATE - 符合Java习惯的关系数据库持久化(第8章)· Hibernate 简化继承映射· Mapping Objects to Relational Databases: O/R Mapping In Detail· Mapping objects to relational databases   下篇文章会谈谈每个子类一个表的策略。

时间: 2024-08-18 07:33:43

Eclipse快速上手Hibernate--4. 继承映射(1)的相关文章

Eclipse快速上手Hibernate--2. 利用Hbm映射文件开发

   这篇文章是上篇文章<Eclipse快速上手Hibernate--1. 入门实例>的延续,主要说的是如何利用Hbm映射文件产生普通的Java对象及数据表.可以参考Hibernate自带的文档<HIBERNATE - 符合Java习惯的关系数据库持久化>的第15章--<工具箱指南>一节.同样,这篇文章没有过多谈理论,只是给出了一个完整的实例加以说明.相关配置请参考上篇文章.  1. 创建项目 ·  新建一个Java项目:HibernateBegin_2,注意选中&qu

Eclipse快速上手Hibernate之入门实例

这篇文章主要谈谈Hibernate的入门开发,例子很简单,就是向数据表中添加用户名和密码.我分别使用了三种方法,一种是直接写代码,写Hbm映射文件等:一种是通过Hbm映射文件来生成代码:一种是通过代码来生成Hbm映射文件.使用了一些自动化工具,XMLBuddy是用来编辑XML文件的,JBoss Eclipse IDE是用来编写Doclet标记的.这篇文章还谈到了一些Eclipse的使用技巧,比如建立"用户库"."生成 Getter 和 Setter"等. 关于一些软

Eclipse快速上手Hibernate--3. 利用XDoclet开发

    这篇文章是上两篇文章<Eclipse快速上手Hibernate--1. 入门实例>和<Eclipse快速上手Hibernate--2. 利用Hbm映射文件开发>的延续,主要说的是如何利用XDocletHbm映射文件产生Hbm映射文件及数据表.可以参考XDoclet文档中关于Hibernate的部分和夏昕编写的<Hibernate开发指南>.同样,这篇文章没有过多谈理论,只是给出了一个完整的实例加以说明.相关配置请参考上两篇文章.  1. 创建项目 ·  新建一个

Eclipse快速上手Hibernate--4. 继承映射(3)

继承     前两篇文章<Eclipse快速上手Hibernate--4. 继承映射(1) >和<继承映射(2)>中已经谈了每个类层次结构一个表(table per class hierarchy)与每个子类一个表(table per subclass)的策略,这篇文章主要说的是每个具体类一个表(table per concrete class).一些重复的部分这里就不说了,请参考前两篇文章.    这个策略很简单,抽象的基类不参与映射,具体子类参与映射.  1. 创建项目 · 

Eclipse快速上手Hibernate--4. 继承映射(2)

继承     上篇文章<Eclipse快速上手Hibernate--4. 继承映射(1) >中已经谈了每个类层次结构一个表(table per class hierarchy)的策略,这篇文章主要说的是每个子类一个表(table per subclass)的策略.一些重复的部分这里就不说了,请参考上篇文章. 1. 创建项目 ·  继续沿用上篇文章中所建的Java项目:InheritanceMapping.   2. 编写类文件 ·  新建一个类,包名:javamxj.inheritance.t

Eclipse快速上手Hibernate--5. 组件映射

    这篇文章主要说的是在Hibernate中的组件(Component)映射,可以参考Hibernate官方文档的第7章.至于环境设置,可以参考这个系列的前面几篇文章.  1. 创建项目 ·  新建一个Java项目:ComponentMapping,注意选中"创建单独的源文件夹和输出文件夹",同时添加"用户库":hibernate.   2. 编写类文件 ·  新建一个类,包名:javamxj.hibernate.component,类名:Person.Pers

Eclipse快速上手Hibernate--1. 入门实例

    这篇文章主要谈谈Hibernate的入门开发,例子很简单,就是向数据表中添加用户名和密码.我分别使用了三种方法,一种是直接写代码,写Hbm映射文件等:一种是通过Hbm映射文件来生成代码:一种是通过代码来生成Hbm映射文件.使用了一些自动化工具,XMLBuddy是用来编辑XML文件的,JBoss Eclipse IDE是用来编写Doclet标记的.这篇文章还谈到了一些Eclipse的使用技巧,比如建立"用户库"."生成 Getter 和 Setter"等.  

Eclipse快速上手指南

Eclipse是一款非常优秀的开源IDE,非常适合Java开发,由于支持插件技术,受到了越来越多的开发者的欢迎.最新的Eclipse 3.0不但界面作了很大的增强,而且增加了代码折叠等众多优秀功能,速度也有明显的提升.配合众多令人眼花缭乱的插件,完全可以满足从企业级Java应用到手机终端Java游戏的开发.本文将带您手把手步入Eclipse的广阔天地,详细介绍在Eclipse下如何开发普通Java程序,Web应用,J2EE应用,手机Java程序,以及如何进行单元测试,重构,配置CVS等详细内容.

Eclipse快速上手指南之使用CVS

版本控制在团队开发中是必不可少的.CVS是优秀的开源版本控制软件,Eclipse本身就内置了对CVS的支持,只需简单配置,即可使用CVS. 首先我们要正确安装并配置好CVS服务器,通常Linux Server都自带CVS服务,不过命令行操作比较繁琐.Windows下也有简单易用的CVS服务器,这里我们推荐CVSNT,可以下载CVSNT 2.0.51a,安装并启动CVSNT: 然后切换到Repositories面板,添加一个Repository,命名为/cvs-java,CVSNT会提示是否初始化