2014年1月11日 星期六

雙向一對一(唯一外鍵關聯) XML Mapping

假設今天一個供應商對應一個銀行帳戶,

但這兩個table有各自的primary key,

我們可以考慮在供應商的table裡面,

增加一個外鍵欄位來連結銀行帳戶,

參考以下的供應商(Supply)和銀行帳戶(BankAccount)的關聯圖,











由於是雙向關聯,

在Supply物件裡會參考至BankAccount物件,

而在BankAccount物件裡也會參考Supply物件,

Supply.java
package com.model;

public class Supply {
 private String code;
 private String name;
 private BankAccount bAccount;
 public String getCode() {
  return code;
 }
 public void setCode(String code) {
  this.code = code;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public BankAccount getbAccount() {
  return bAccount;
 }
 public void setbAccount(BankAccount bAccount) {
  this.bAccount = bAccount;
 }
}

BankAccount.java
package com.model;

public class BankAccount {
 private String accountNumber;
 private String bankName;
 private Supply supply;
 public String getAccountNumber() {
  return accountNumber;
 }
 public void setAccountNumber(String accountNumber) {
  this.accountNumber = accountNumber;
 }
 public String getBankName() {
  return bankName;
 }
 public void setBankName(String bankName) {
  this.bankName = bankName;
 }
 public Supply getSupply() {
  return supply;
 }
 public void setSupply(Supply supply) {
  this.supply = supply;
 }
}

在使用外鍵來完成一對一關聯,

即是在多對一的關係中,

限制多的一方只能有一個去對應到一的一方,

可參考以下的配置,

Supply.hbm.xml
<?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>
 <class name="com.model.Supply" table="supply">
  <id name="code" type="java.lang.String">
   <generator class="assigned" />
  </id>
  <property name="name" type="string">
   <column name="name" length="20" not-null="true" />
  </property>
  <many-to-one name="bAccount" class="com.model.BankAccount"
   cascade="all" outer-join="true" unique="true">
   <column name="accountNumber" />
  </many-to-one>
 </class>
</hibernate-mapping>

在many-to-one的配置中,

我們使用了unique="true"來限制必須為一對一關聯,

cascade="all"表示所有情況下皆進行關聯(save、update、delete),

outer-join="true"表示使用一條SQL查詢並join關聯table,

另外在BankAccount.hbm.xml中使用one-to-one來完成雙向一對一關係,

BankAccount.hbm.xml
<?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>
 <class name="com.model.BankAccount" table="bankaccount">
  <id name="accountNumber" type="java.lang.String">
   <generator class="assigned" />
  </id>
  <property name="bankName" type="string">
   <column name="bankName" length="20" not-null="true" />
  </property>
  <one-to-one name="supply" property-ref="bAccount" class="com.model.Supply" />
 </class>
</hibernate-mapping>

在one-to-one中使用property-ref來指定參照到supply裡面的bAccount,

參考測試程式:

TestSupplyBank.java
package com.hibernate;

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.hibernate.util.HibernateUtils;
import com.model.BankAccount;
import com.model.Supply;

public class TestSupplyBank {

 public static void main(String[] args) {

  Session session = HibernateUtils.getSessionFactory().openSession();
  Transaction tx = session.beginTransaction();
  try {
   Supply aSupply=new Supply();
   BankAccount bankAccount=new BankAccount();
   aSupply.setCode("WDR12345");
   aSupply.setName("ABC公司");
   bankAccount.setAccountNumber("1652-2323-1212-1232");
   bankAccount.setBankName("大大銀行");
   aSupply.setbAccount(bankAccount);
   bankAccount.setSupply(aSupply);
   
   session.save(aSupply);
   
   tx.commit();
  } catch (Exception e) {
   tx.rollback();
   e.printStackTrace();
  } finally {
   session.close();
   HibernateUtils.shutdown();
  }
 }

}

執行結果如下:

Hibernate: select bankaccoun_.accountNumber, bankaccoun_.bankName as bankName3_ from bankaccount bankaccoun_ where bankaccoun_.accountNumber=?
Hibernate: insert into bankaccount (bankName, accountNumber) values (?, ?)
Hibernate: insert into supply (name, accountNumber, code) values (?, ?, ?)


第一條select是由於這是創一個新的物件,

hibernate在緩存中也找不到,

為了確認這個關聯物件是可以插入到DB裡的,

所以先進行一次select尋找,

可看到table的資料如下:

table supply












table bankaccount


沒有留言:

張貼留言