SSH開發實踐part2:雙向1-N連線配置

大魔王薩格拉斯發表於2014-06-16

 

1  

  OK,上一篇已經介紹了專案開發的前期準備工作,具體內容可以參考:http://www.cnblogs.com/souvenir/p/3783686.html

  按照開發步驟,我們現在已經可以開始進行業務邏輯元件層的開發工作了。但是之前只寫了一個bean,而且結構也相對很簡單,對於大型專案來說肯定是不夠的,所以

  本章節的重點就是來建立更多的bean物件,為後面的邏輯元件開發做好準備工作。

  對了,忘了介紹,我們是根據書上需求,準備做一個簡單的HR系統,包括簡單的請假,查工資等功能。

2

  有人肯定疑惑了,之前已經做了一個bean的參考,其他的bean照著做不就行了嗎,為什麼還要單獨講。

  好吧,之前的employee只是一個非常簡單的bean,在現實的開發專案中肯定有很多關係複雜的bean,我們要通過hibernate以及spring來完成對

  他們的管理和呼叫。ok,話不多少,下面開始吧。

3  

  現在我們做一個員工工資實體物件,具體屬性包括id,emp,year,month,amount。

  先完成payment物件:

  對了,這裡bean物件實現了Serializable介面,主要為了方便物件的例項化,不清楚的可以百度一下。

public class Payment implements Serializable{

    private static final long serialVersionUID = 99L;
    private int id;
    private Employee emp;
    private int year;
    private int month;
    private double salary;
}

  篇幅問題,我們省略了各屬性的set與get方法以及物件的建構函式。

  這個bean和之前的employee沒有什麼大的區別,主要是多了一個對其他物件的引用。

4  

  建立好bean物件以後,我們來建立hibernate對映檔案。

<hibernate-mapping package="com.souvenir.bean">
    <class name="Payment" table="Payment">
        <!-- 對映標識屬性 -->
        <id name="id" column="payment_id"
            type="int">
            <!-- 指定主鍵生成器策略 -->
            <generator class="identity"/>
        </id>
        <!-- 對映普通屬性 -->
        <property name="year" type="int"/>
        <property name="month" type="int"/>
        <property name="salary" type="double"/>
        <many-to-one name="emp" class="Employee" lazy="false" not-null="true" column="emp_id"/>
    </class>
</hibernate-mapping>

  OK,唯一需要強調的就是對emp這個物件的處理。員工的工資物件與員工應該是多對一的關係,因為一個員工可以有多份工資嘛。

  所以這裡用了<many-to-one>來完成與emp的對映,使用class來指定其關聯的物件類名,同時可以指定其在資料庫表中的列名。

  這樣就基本上完成了。

  需要提個醒的是,也是樓主剛開始犯錯的地方,這裡配置檔案的name屬性一定要和你定義的bean java檔案中的屬性名稱一致,要不然系統會

  提示找不到對應的set/get函式。

 

5 雙向1-N關聯配置

  對於1-N的關聯關係,hibernate是推薦使用雙向1-N關聯配置,因為可以方便互相呼叫。

  在本例中,employee就是1,payment就是N端,要實現二者的相互關聯,需要如下設定:

  1端bean增加Set<N端>屬性,以及相應的get/set函式

  N端bean增加1端的物件屬性,以及對應的get/set函式

  這裡payment我們已經新增了employee的屬性,對於之前編寫的employee類來說,我們也需要增加Set<Payment>配置

private Set<Payment> payments= new HashSet<Payment>();

  

  對於hibernate xml配置,employee也要做相應的調整:

    <!-- 對映和Payment之間的關聯關係 -->
        <set name="payments" inverse="true" lazy="false">
            <key column="emp_id" />
            <one-to-many class="Payment"/>
        </set>

  對應雙向1-N的關聯關係來說,一般是通過控制N端進行關聯關係控制,所以這裡我們把1端employee加上inverse=true屬性

  兩個配置檔案中的one-to-many以及many-to-one的column值需要保持一致,hibernate通過這個值進行表的關聯。

  上面我們用的是沒有關聯表的配置,大家也可以嘗試通過關聯表來實現,效果都一樣,只是資料庫中對出現一箇中間的關聯連線表。

 

6  還是測試

  完成上述開發以後,我們就可以在main函式裡面進行測試了。

  1.資料的建立:由於是雙向1-N關聯,所以通過N端進行關聯控制。體現在程式碼實現過程中就是先建立好N端物件,然後往N端物件中設定1端物件。

        for(int i=1;i<=10;i++){
            System.out.println("oooo==="+i);
            empDao.save(new Employee("souvenir"+i,i+1,"password"+i));
        }
        
        Employee emp=empDao.get(2);
        
        //雙向1-N  讓N端來控制關聯關係
        for(int j=1;j<=12;j++){
            Payment payment=new Payment(2014,j,j*1002);
            payment.setEmp(emp);
            payDao.save(payment);
        }

  上述程式碼主要實現以下功能:先建立10個employee物件,然後取出其中一個,然後建立12個payment物件,並將其全部的employee屬性都設定同一個。

 

  2.既然是雙向連線,也就是說我們通過任一一端都可以取到對應的另一端。比如先通過N(payment)端訪問1(employee)端

 Payment payment=payDao.get(2);
System.out.println(payment.getEmp().getName()
+"--"+payment.getEmp().getPassword());

  我們先拿一個N端物件payment,然後通過get函式取到employee物件。

 

  3.通過1(employee)端訪問N(payment)端

    Set<Payment> payments=empDao.get(2).getPayments();
        for(Payment p: payments){
            System.out.println(p.getYear()+"-"+p.getMonth()+":"+p.getSalary());
        }

  也就是說,我們通過人找到其對應的所有payment物件,這種業務也是比較常見的。

  

相關文章