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

來源:互聯網
上載者:User
繼承    前面的《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   下篇文章會談談每個子類一個表的策略。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.