如上圖,是一個銷售系統的資料庫關聯圖,這個關聯圖說明 了以下關係:
- 一個銷售人員會有許多客戶,每個客戶則會歸屬到一個銷售人員下進行服務。
- 每個客戶會購買一到多個商品,同時一個商品也會賣給一到多個客戶。
- SALES 主動 ("一"方主動)
根據上面的關聯圖,建立 SALES 和 CUSTOMER 兩個 table 的類別,如下,建構子的部份是為了後面的需求而加上去,與關聯圖無關,請先忽略,重點在於變數及其相對應的 getter & setter method。 Sales 類別的變數除了 table 中的兩個欄位各建立一個變數外,為了表示出和 Customer 的一對多關係,增加了 customer 這個變數,用來儲存所關聯到客戶,因為客戶個數會有多個,以 Set 來承載。
public class Sales implements Serializable { private String emNo; private String name; private Set<Customer> customer; public Sales() {} public Sales(String emNo, String name) { this.emNo = emNo; this.name = name; } public Sales(String emNo, String name, Set<Customer> customer) { this.emNo = emNo; this.name = name; this.customer = this.customer; } public String getEmNo() { return emNo; } public void setEmNo(String emNo) { this.emNo = emNo; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Collection<Customer> getCustomer() { return customer; } public void setCustomer(Set<Customer> customer) { this.customer = customer; } }
Customer 類別在表現 table CUSTOMER 時,因為是被動的一方,只要依 table 上的欄位建立相關的變數,並給予 getter & setter method 就可以了。
public class Customer implements java.io.Serializable {
private String cid;
private String name;
private String emNo;
public Customer(String cid, String name) {
this.cid = cid;
this.name = name;
}
public Customer(String cid, String name, String emNo) {
this.cid = cid;
this.name = name;
this.emNo = emNo;
}
public String getCid() {
return cid;
}
public void setCid(String cid) {
this.cid = cid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmNo() {
return emNo;
}
public void setEmNo(String emNo) {
this.emNo = emNo;
}
}
- 注意看一下 hibernate-mapping 的屬性 package,那是 Java 類別所在的 package,這個屬性可以不寫,而在後面其它 tag 的 class 屬性中,寫出類別的全域名稱。
- set tag 要對應到 class SALES 中的 customer 的型別,除了用 Set 外,還有許多選擇,之後再說明。
- cascade 屬性有許多的選項,這裡寫 all 當然就是全部的選項都包括,選項有 save-update、delete、 delete-orphan,用來指定關聯的屬性。
- SALES 和 CUSTOMER 間的關係為一對屬,所以要加上 one-to-many 的 tag。
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="idv.steven.orm.market">
<class name="Sales" table="SALES">
<id name="emNo" type="java.lang.String">
<column name="EMNO" />
<generator class="assigned" />
</id>
<property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<set name="customer" table="CUSTOMER" inverse="true" cascade="all">
<key column="EMNO" not-null="true" />
<one-to-many class="Customer" />
</set>
</class>
</hibernate-mapping>
- CUSTOMER 依類別那樣,因為是被動的,也只是將 table 裡的欄位定義好就可以了。
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="idv.steven.orm.market">
<class name="Customer" table="CUSTOMER">
<id name="cid" type="java.lang.String">
<column name="CID" />
<generator class="assigned" />
</id>
<property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<property name="emNo" type="java.lang.String">
<column name="EMNO" />
</property>
</class>
</hibernate-mapping>
注意看一下程式,只有最後兩行將資料儲存到 table SALES,但是,實際查詢資料庫會發現,table CUSTOMER 裡也多了三筆資料,這就是上面的類別和 xml 設定為什麼要說定那些關聯的緣故,透過這些關聯,Hibernate 會將相關的資料一併處理 (儲存、更新或刪除)。
Sales s1 = new Sales("007528", "黃藥師");
Sales s2 = new Sales("001569", "江湖郎中");
Customer c1 = new Customer("1000000001", "張無忌", s1);
Customer c2 = new Customer("2000000025", "趙敏", s1);
Customer c3 = new Customer("2000000337", "周芷若", s2);
Set<Customer> sc1 = new HashSet<Customer>();
sc1.add(c1);
sc1.add(c2);
s1.setCustomer(sc1);
Set<Customer> sc2 = new HashSet<Customer>();
sc2.add(c3);
s2.setCustomer(sc2);
session.save(s1);
session.save(s2);
- CUSTOMER 主動 ("多"方主動)
如下,Sales 類別毫無懸念的依照 table layou 定義即可,要注意的是 Customer 類別,現在它是主動方,所以原本的 emNo 欄位拿掉,換成一個指向 Sales 類別的變數 -- sales,這就像是在建立 foreign key。
public class Sales implements Serializable {
private String emNo;
private String name;
public Sales(String emNo, String name) {
this.emNo = emNo;
this.name = name;
}
public String getEmNo() {
return emNo;
}
public void setEmNo(String emNo) {
this.emNo = emNo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Customer implements java.io.Serializable {
private String cid;
private String name;
private Sales sales;
public Customer(String cid, String name) {
this.cid = cid;
this.name = name;
}
public Customer(String cid, String name, Sales sales) {
this.cid = cid;
this.name = name;
this.sales = sales;
}
public String getCid() {
return cid;
}
public void setCid(String cid) {
this.cid = cid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Sales getSales() {
return sales;
}
public void setSales(Sales sales) {
this.sales = sales;
}
}
接下來看 xml 設定檔 … Sales.hbm.xml 也是毫無懸念的,因為是被動端,完全依資料庫的定義設定。Customer.hbm.xml 中要注意的是如何定義多對一的關係? 這裡引入了 many-to-one 這個 tag,它的屬性前面基本上都有說明過,不再重複。
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="idv.steven.orm.market">
<class name="Sales" table="SALES">
<id name="emNo" type="java.lang.String">
<column name="EMNO" />
<generator class="assigned" />
</id>
<property name="name" type="java.lang.String">
<column name="NAME" />
</property>
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="idv.steven.orm.market">
<class name="Customer" table="CUSTOMER">
<id name="cid" type="java.lang.String">
<column name="CID" />
<generator class="assigned" />
</id>
<property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<many-to-one name="sales" class="Sales" column="EMNO" cascade="all" not-null="true" />
</class>
</hibernate-mapping>
Sales s1 = new Sales("007528", "黃藥師"); Sales s2 = new Sales("001569", "江湖郎中"); Customer c1 = new Customer("1000000001", "張無忌", s1); Customer c2 = new Customer("2000000025", "趙敏", s1); Customer c3 = new Customer("2000000337", "周芷若", s2); session.save(c1); session.save(c2); session.save(c3);
- 雙向關聯
Hibernate 建議,在一對多的狀況下,最好是雙向關聯,且由多方主動。
** Source Code: https://bitbucket.org/twleader59/orm
沒有留言:
張貼留言