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

    前兩篇文章《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 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"/>
 
· 先運行MySQL,然後雙擊“schemaexport”任務,在項目根目錄下,會更新“schema-export.sql”文件。
打開這個文件,會發現添加了以下一些語句。 
create table Student (
   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)
)
 
·  切換到數據庫中,會發現已經自動產生了數據表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)映射。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章