Google Code Prettify

2016年2月10日 星期三

Hibernate: many-to-many (xml)



上一篇完成了 one-to-many,這篇要說明多對多的狀況 (many-to-many),也就是第 2 個情節,客戶訂購商品,相關的 table 有 CUSTOMER、GOODS 及 ORDERS。
以物件的視角來看客戶和商品,我們了解彼此間是多對多的關係,即一個客戶可以購買多種商品,一種商品也可以賣給多個客戶,所以在程式中會定義 Customer、Goods 兩個類別,並於類別中指出彼此的關係。但是,在關聯式資料庫,多對多的關係必須引進第三個 table,在這裡就是 ORDERS,利用它來指出 CUSTOMER 和 GOODS 間的多對多關係,如上的 table layout,ORDERS 中每筆資料會有 CID 及 GID 欄位,指出這筆訂單是屬於那個客戶及購買了那一項商品。接下來看類別如何定義 …
底下的類別 Customer,我們延續上一篇的程式,再增加 goods 變數,用來指出一個客戶可以購買多項商品。在類別 Goods 中,同樣的也有個變數 customer,用來指出一項商品可以賣給多個客戶。table ORDERS 要給它一個類別嗎?? 答案是要! 簡單的給它一個 POJO 就可以了,hibernate 會用到!
public class Customer implements java.io.Serializable {
    private String cid;
    private String name;
    private Sales sales;
    
    private Set<Goods> goods = new HashSet<Goods>();
    
    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;
    }

    public Set<Goods> getGoods() {
        return goods;
    }

    public void setGoods(Set<Goods> goods) {
        this.goods = goods;
    }
    
    public void addGoods(Goods g) {
        goods.add(g);
    }
}
public class Goods {
    private String gid;
    private String name;
    
    private Set<Customer> customer = new HashSet<Customer>();
    
    public Goods(String gid, String name) {
        this.gid = gid;
        this.name = name;
    }
    
    public Goods(String gid, String name, Set<Customer> customer) {
        this.gid = gid;
        this.name = name;
        this.customer = customer;
    }
    
    public String getGid() {
        return gid;
    }
    public void setGid(String gid) {
        this.gid = gid;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Set<Customer> getCustomer() {
        return customer;
    }
    public void setCustomer(Set<Customer> customer) {
        this.customer = customer;
    }
    
    public void addCustomer(Customer c) {
        customer.add(c);
    }
}
public class Orders {
    private String cid;
    private String gid;
    
    public String getCid() {
        return cid;
    }
    public void setCid(String cid) {
        this.cid = cid;
    }
    public String getGid() {
        return gid;
    }
    public void setGid(String gid) {
        this.gid = gid;
    }
}
xml 設定檔如下,最重要的是綠色部份,在類別中只以商業需求的角度指出客戶和商品的關係,實際上怎麼儲存到資料庫? 這就要在設定檔中交代清楚,從下面的設定檔,可以看到 Customer 類別中的 goods 變數,實際上是透過 ORDERS 這個 table 為中介與 Goods 產生多對多的關係,Goods 類別中的 customer 變數也一樣,是透過 ORDERS 這個 table 為中介與 Customer 產生多對多關係。
<?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" />
        
        <set name="goods" table="ORDERS" inverse="false" lazy="true" cascade="all">
            <key>
                <column name="CID" not-null="true"/>
            </key>
            <many-to-many column="GID" class="Goods" />
        </set>
    </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="Goods" table="GOODS">
        <id name="gid" type="java.lang.String">
            <column name="GID" />
            <generator class="assigned" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        
        <set name="customer" table="ORDERS" inverse="true" lazy="true">
            <key>
                <column name="GID" not-null="true" />
            </key>
            <many-to-many column="CID" class="Customer" />
        </set>
    </class>
</hibernate-mapping>
最後當然要看一下程式怎麼寫,如下:
Sales s3 = new Sales("008527", "百曉生");
Customer c4 = new Customer("5000005006", "未來事件預測商社", s3);
Set<Customer> customer = new HashSet<Customer>();
customer.add(c4);
Goods g1 = new Goods("AZ00000001", "陰陽和合散", customer);
c4.addGoods(g1);
        
session.save(c4);
執行結果應該可以看到,table SALES、CUSTOMER、GOODS、ORDERS 都有相關的資料。上面的程式是新的客戶購買商品,如果是既有客戶,程式要怎麼寫? 如下:
Customer c2 = session.get(Customer.class, "2000000025");

Goods g2 = new Goods("6Z00001001", "百花消魂散");
g2.addCustomer(c2);
c2.addGoods(g2);

session.save(c2);



沒有留言:

張貼留言