程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 精通Hibernate之映射繼承關系三

精通Hibernate之映射繼承關系三

編輯:關於JAVA

<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());
}else
System.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表插入一條記錄。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved