国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

精通Hibernate映射繼承關系之二

2019-11-18 16:11:47
字體:
來源:轉載
供稿:網友

  把每個具體類映射到一張表是最簡單的映射方式。如圖14-2所示,在關系數據模型中只需定義COMPANIES、HOURLY_EMPLOYEES和SALARIED_EMPLOYEES表。為了敘述的方便,下文把HOURLY_EMPLOYEES表簡稱為HE表,把SALARIED_EMPLOYEES表簡稱為SE表。

HourlyEmployee類和HE表對應,HourlyEmployee類本身的rate屬性,以及從Employee類中繼承的id屬性和name屬性,在HE表中都有對應的字段。此外,HourlyEmployee類繼承了Employee類與Company類的關聯關系,與此對應,在HE表中定義了參照COMPANIES表的COMPANY_ID外鍵。

SalariedEmployee類和SE表對應,SalariedEmployee類本身的salary屬性,以及從Employee類中繼承的id屬性和name屬性,在SE表中都有對應的字段。此外,SalariedEmployee類繼承了Employee類與Company類的關聯關系,與此對應,在SE表中定義了參照COMPANIES表的COMPANY_ID外鍵。

Company類、HourlyEmployee類和SalariedEmployee類都有相應的映射文件,而Employee類沒有相應的映射文件。圖14-3顯示了持久化類、映射文件和數據庫表之間的對應關系。

精通Hibernate映射繼承關系之二(圖一)


圖14-2 每個具體類對應一個表


精通Hibernate映射繼承關系之二(圖二)


圖14-3 持久化類、映射文件和數據庫表之間的對應關系
如果Employee類不是抽象類,即Employee類本身也能被實例化,那么還需要為Employee類創建對應的EMPLOYEES表,此時HE表和SE表的結構仍然和圖14-2中所示的一樣。這意味著在EMPLOYEES表、HE表和SE表中都定義了相同的NAME字段以及參照COMPANIES表的外鍵COMPANY_ID。另外,還需為Employee類創建單獨的Employee.hbm.xml文件。

14.1.1 創建映射文件

從Company類到Employee類是多態關聯,但是由于關系數據模型沒有描述Employee類和它的兩個子類的繼承關系,因此無法映射Company類的employees集合。例程14-1是Company.hbm.xml文件的代碼,該文件僅僅映射了Company類的id和name屬性。

例程14-1 Company.hbm.xml


<hibernate-mapping ><class name="mypack.Company" table="COMPANIES" ><id name="id" type="long" column="ID"><generator class="increment"/></id><PRoperty name="name" type="string"  column="NAME" /></class></hibernate-mapping>


HourlyEmployee.hbm.xml文件用于把HourlyEmployee類映射到HE表,在這個映射文件中,除了需要映射HourlyEmployee類本身的rate屬性,還需要映射從Employee類中繼承的name屬性,此外還要映射從Employee類中繼承的與Company類的關聯關系。例程14-2是HourlyEmployee.hbm.xml文件的代碼。

例程14-2 HourlyEmployee.hbm.xml

<hibernate-mapping >      <class name="mypack.HourlyEmployee" table="HOURLY_EMPLOYEES">      <id name="id" type="long" column="ID">        <generator class="increment"/>      </id>         <property name="name" type="string" column="NAME" />      <property name="rate" column="RATE" type="double" />      <many-to-one        name="company"        column="COMPANY_ID"        class="mypack.Company"      />      </class>      </hibernate-mapping>                                                  


 

SalariedEmployee.hbm.xml文件用于把SalariedEmployee類映射到SE表,在這個映射文件中,除了需要映射SalariedEmployee類本身的salary屬性,還需要映射從Employee類中繼承的name屬性,此外還要映射從Employee類中繼承的與Company類的關聯關系。例程14-3是SalariedEmployee.hbm.xml文件的代碼。

例程14-3 SalariedEmployee.hbm.xml

<hibernate-mapping >      <class name="mypack.SalariedEmployee" table="SALARIED_EMPLOYEES">      <id name="id" type="long" column="ID">        <generator class="increment"/>      </id>         <property name="name" type="string" column="NAME" />      <property name="salary" column="SALARY" type="double" />      <many-to-one        name="company"        column="COMPANY_ID"        class="mypack.Company"      />      </class>      </hibernate-mapping>         



由于Employee類沒有相應的映射文件,因此在初始化Hibernate時,只需向Configuration對象中加入Company類、HourlyEmployee類和SalariedEmployee類:

Configuration config = new Configuration();config.addClass(Company.class).addClass(HourlyEmployee.class).addClass(SalariedEmployee.class);



14.1.2 操縱持久化對象

這種映射方式不支持多態查詢,在本書第11章的11.1.6節(多態查詢)介紹了多態查詢的概念。對于以下查詢語句:

List employees=session.find("from Employee");
如果Employee類是抽象類,那么Hibernate會拋出異常。如果Employee類是具體類,那么Hibernate僅僅查詢EMPLOYEES表,檢索出Employee類本身的實例,但不會檢索出它的兩個子類的實例。本節的范例程序位于配套光盤的sourcecode/chapter14/14.1目錄下,運行該程序前,需要在SAMPLEDB數據庫中手工創建COMPANIES表、HE表和SE表,然后加入測試數據,相關的SQL腳本文件為/14.1/schema/sampledb.sql。

在chapter14目錄下有四個ANT的工程文件,分別為build1.xml、build2.xml、build3.xml和build4.xml,它們的區別在于文件開頭設置的路徑不一樣,例如在build1.xml文件中設置了以下路徑:



<property name="source.root" value="14.1/src"/><property name="class.root" value="14.1/classes"/><property name="lib.dir" value="lib"/><property name="schema.dir" value="14.1/schema"/>


在DOS命令行下進入chapter14根目錄,然后輸入命令:

ant  -file  build1.xml  run


就會運行BusinessService類。ANT命令的-file選項用于顯式指定工程文件。BusinessService類用于演示操縱Employee類的對象的方法,例程14-4是它的源程序。

例程14-4 BusinessService.java


public class BusinessService{public static SessionFactory sessionFactory;static{try{Configuration config = new Configuration();config.addClass(Company.class).addClass(HourlyEmployee.class).addClass(SalariedEmployee.class);sessionFactory = config.buildSessionFactory();}catch(Exception e){e.printStackTrace();}}public void saveEmployee(Employee employee) throws Exception{……}public List findAllEmployees() throws Exception{……}public Company loadCompany(long id) throws Exception{……}public void test() throws Exception{List employees=findAllEmployees();printAllEmployees(employees.iterator());Company company=loadCompany(1);printAllEmployees(company.getEmployees().iterator());Employee employee=new HourlyEmployee("Mary",300,company);saveEmployee(employee);}private void printAllEmployees(Iterator it){while(it.hasNext()){Employee e=(Employee)it.next();if(e instanceof HourlyEmployee){System.out.println(((HourlyEmployee)e).getRate());}elseSystem.out.println(((SalariedEmployee)e).getSalary());}}public static void main(String args[]) throws Exception {new BusinessService().test();sessionFactory.close();}}BusinessService的main()方法調用test()方法,test()方法依次調用以下方法。findAllEmployees():檢索數據庫中所有的Employee對象。loadCompany():加載一個Company對象。saveEmployee():保存一個Employee對象。


(1)運行findAllEmployees()方法,它的代碼如下:

List results=new ArrayList();tx = session.beginTransaction();List hourlyEmployees=session.find("from HourlyEmployee");results.addAll(hourlyEmployees);List salariedEmployees=session.find("from SalariedEmployee");results.addAll(salariedEmployees);tx.commit();return results;


為了檢索所有的Employee對象,必須分別檢索所有的HourlyEmployee實例和SalariedEmployee實例,然后把它們合并到同一個集合中。在運行Session的第一個find()方法時,Hibernate執行以下select語句:


select * from HOURLY_EMPLOYEES;select * from COMPANIES where ID=1;


從HourlyEmployee類到Company類不是多態關聯,在加載HourlyEmployee對象時,會同時加載與它關聯的Company對象。

在運行Session的第二個find()方法時,Hibernate執行以下select語句:

select * from SALARIED_EMPLOYEES;


從SalariedEmployee類到Company類不是多態關聯,在加載SalariedEmployee對象時,會同時加載與它關聯的Company對象。在本書提供的測試數據中,所有HourlyEmployee實例和SalariedEmployee實例都與OID為1的Company對象關聯,由于該Company對象已經被加載到內存中,所以Hibernate不再需要執行檢索該對象的select語句。

(2)運行loadCompany()方法,它的代碼如下:

tx = session.beginTransaction();Company company=(Company)session.load(Company.class,new Long(id));List hourlyEmployees=session.find("from HourlyEmployee h where h.company.id="+id);company.getEmployees().addAll(hourlyEmployees);List salariedEmployees=session.find("from SalariedEmployee s where s.company.id="+id);
company.getEmployees().addAll(salariedEmployees);tx.commit();return company;


由于這種映射方式不支持多態關聯,因此由Session的load()方法加載的Company對象的employees集合中不包含任何Employee對象。BusinessService類必須負責從數據庫中檢索出所有與Company對象關聯的HourlyEmployee對象以及SalariedEmployee對象,然后把它們加入到employees集合中。

(3)運行saveEmployee(Employee employee)方法,它的代碼如下:

tx = session.beginTransaction();session.save(employee);tx.commit();


在test()方法中,創建了一個HourlyEmployee實例,然后調用saveEmployee()方法保存這個實例:

Employee employee=new HourlyEmployee("Mary",300,company);saveEmployee(employee);


Session的save()方法能判斷employee變量實際引用的實例的類型,如果employee變量引用HourlyEmployee實例,就向HE表插入一條記錄,執行如下insert語句:

insert into HOURLY_EMPLOYEES(ID,NAME,RATE,CUSTOMER_ID)values(3, 'Mary',300,1);


如果employee變量引用SalariedEmployee實例,就向SE表插入一條記錄。

(出處:http://m.survivalescaperooms.com)



發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 伊吾县| 土默特右旗| 定州市| 浮梁县| 光泽县| 日喀则市| 威远县| 丁青县| 堆龙德庆县| 搜索| 青阳县| 寻乌县| 高碑店市| 沁水县| 兰坪| 彭阳县| 万盛区| 盐城市| 佛冈县| 安远县| 北海市| 龙井市| 德钦县| 陈巴尔虎旗| 九寨沟县| 凤台县| 泰和县| 嘉义市| 河曲县| 司法| 罗城| 博客| 湟源县| 巢湖市| 通州区| 柳州市| 托克托县| 佛冈县| 布拖县| 华阴市| 辽宁省|