· 每個具體類一個表(table per concrete class)(有一些限制)
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(); }
Cat.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.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; } } |
· 在項目根目錄下建立一個build.xml,要注意的是環境變量和數據庫的設置要符合自己的實際配置,這裏庫文件目錄的設置是"D:/java/Hibernate/lib",參考文章《Eclipse快速上手Hibernate--1. 入門實例》中的設置。
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> <!-- &amp; --> <property name="hibernate.jdbc.url" value="jdbc:mysql://localhost:3306/HibernateTest?useUnicode=true&amp;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" /> <!-- 生成配置文件 --> <hibernatecfg dialect="${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>
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.xml containing 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.xml containing 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> |
schema-export.sql |
drop table if exists Animal drop table if exists hibernate_unique_key create 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 ) |
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(); } } }
· 實現簡單。
· 支持多態——對象角色發生變化,或存在多重角色時。
· 報表操作實現簡單:表中包含了所有信息。
● 缺點:
· 增加類層次中的耦合。類層次中任何類的屬性的增加都會導致表的變更;某個子類屬性的修改會影響到整個
層次結構,而不僅僅是該子類。
· 浪費了一些數據庫空間。浪費空間的多少取決於繼承層次的深度。層次越深,不同的屬性越多,屬性的全集就越大,也就越浪費空間。
· 可能需要指明具體的角色。