Hibernate中的關聯(lián)(Association)映射主要有三種:一對一關聯(lián),一對多(或多對一)關聯(lián),多對多關聯(lián)。每種關聯(lián)都可以分為單向和雙向兩種。
這篇文章主要說的是在Hibernate中的一對一關聯(lián),可以參考Hibernate官方文檔的第5章。至于環(huán)境設置,可以參考這個系列的前面幾篇文章。
一對一關聯(lián)有兩種映射方式:一種是使用主鍵關聯(lián),限制兩個數據表的主鍵使用相同的值;另一種是一個外鍵和一個惟一關鍵字對應。
這里用關聯(lián)映射將上篇文章
《組件映射》改寫了一下,一個人對應一個地址,這是一個單向關聯(lián),先談談如何使用主鍵關聯(lián)。
1. 創(chuàng)建項目
· 新建一個Java項目:AssociationMapping,注意選中“創(chuàng)建單獨的源文件夾和輸出文件夾”,同時添加“用戶庫”:hibernate。
2. 編寫類文件
· 新建一個類,包名:javamxj.hibernate.association.one2one,類名:Person。
/* * Hibernate - 關聯(lián)(Association)映射 * 創(chuàng)建日期 2005-4-25 * @author javamxj(分享java快樂) * @link Blog: htpp://blog.csdn.net/javamxj/ * htpp://javamxj.mblogger.cn */package javamxj.hibernate.association.one2one;/** * @hibernate.class table = "T_Person" */public class Person { private Long id; private String username; private Address address; /** * @hibernate.id * generator-class="foreign" * @hibernate.generator-param * name="property" * value="address" */ public Long getId() {return id;} public void setId(Long id) {this.id = id;} /** * @hibernate.property * length="15" * not-null="true" */ public String getUsername() {return username;} public void setUsername(String username) {this.username = username;} /** * @hibernate.one-to-one * cascade="all" */ public Address getAddress() {return address;} public void setAddress(Address address) {this.address = address;}}
· 注意Person類的主鍵生成方式是“foreign”,使其參考Address類的主鍵。
· 在最后幾行中指明了如何引用Address類的方式,其中cascade="all" 表示所有情況下均進行級聯(lián)操作。
· 這里將Address類獨立映射為一個表。
package javamxj.hibernate.association.one2one;/** * @hibernate.class table = "T_Address" */public class Address { private String country; private String city; private String street; private String zipCode; private Long id; public Address() {} public Address(String country, String city, String street, String zipcode) { super(); this.country = country; this.city = city; this.street = street; this.zipCode = zipcode; } /** * @hibernate.id * generator-class="hilo" * unsaved-value="null" */ public Long getId() { return id; } public void setId(Long id) { this.id = id; } /** * @hibernate.property * length = "12" */ public String getCity() {return city;} public void setCity(String city) {this.city = city;} /** * @hibernate.property * length = "12" */ public String getCountry() {return country;} public void setCountry(String country) {this.country = country;} /** * @hibernate.property * length = "6" */ public String getZipCode() {return zipCode;} public void setZipCode(String number) {this.zipCode = number;} /** * @hibernate.property * length = "12" */ public String getStreet() {return street;} public void setStreet(String street) {this.street = street;} }
· 雙擊“generate-hbm”任務,會發(fā)現(xiàn)在包中產生了Person.hbm.xml和Address.hbm.xml文件,在src目錄下會多了一個hibernate.cfg.xml文件,如果沒有,按F5鍵刷新一下。
· 看看Person類的映射文件中的重點部分:
<generator class="foreign">
<param name="property">address</param>
<!--
To add non XDoclet generator parameters, create a file named
hibernate-generator-params-Person.xml
containing the additional parameters and place it in your merge dir.
-->
</generator>
<one-to-one
name="address"
class="javamxj.hibernate.association.one2one.Address"
cascade="all"
outer-join="auto"
constrained="false"
/>
· 運行MySql服務器,然后雙擊“schemaexport”任務,在項目根目錄下,會產生一個“schema-export.sql”文件。
· 切換到數據庫中,會發(fā)現(xiàn)已經自動產生了數據表T_Person和T_Address。
4. 測試程序
· 好了,在包javamxj.hibernate.association.one2one下新建一個Demo.java文件。
package javamxj.hibernate.association.one2one;import net.sf.hibernate.HibernateException;import net.sf.hibernate.Session;import net.sf.hibernate.SessionFactory;import net.sf.hibernate.Transaction;import net.sf.hibernate.cfg.Configuration;public class Demo { public static void main(String[] args) throws HibernateException { Address address1 = new Address("中國", "上海", "普陀", "200055"); Person p1 = new Person(); p1.setUsername("JavaMXJ"); p1.setAddress(address1); Address address2 = new Address("中國", "北京", "海淀", "100086"); Person p2 = new Person(); p2.setUsername("張三"); p2.setAddress(address2); SessionFactory sf = new Configuration().configure().buildSessionFactory(); Session sess = sf.openSession(); Transaction tx= sess.beginTransaction(); sess.save(p1); sess.save(p2); tx.commit(); sess.close(); sf.close(); }}
· 運行這個類,數據表中生成如下數據:
注意這兩個表中的主鍵值相同的。
· 最后的項目結構如下:
5. 另一種映射方式
這里簡單說說一個外鍵和一個惟一關鍵字對應的方式。
以上面的文章為基礎,只要改動一下Person.java即可。
/* * Hibernate - 關聯(lián)(Association)映射 * 創(chuàng)建日期 2005-4-25 * @author javamxj(分享java快樂) * @link Blog: htpp://blog.csdn.net/javamxj/ * htpp://javamxj.mblogger.cn */package javamxj.hibernate.association.one2one;/** * @hibernate.class table = "T_Person" */public class Person { private Long id; private String username; private Address address; /** * @hibernate.id * generator-class="hilo" * unsaved-value="null" */ public Long getId() {return id;} public void setId(Long id) {this.id = id;} /** * @hibernate.property * length="15" * not-null="true" */ public String getUsername() {return username;} public void setUsername(String username) {this.username = username;} /** * @hibernate.many-to-one * column = "fk_Address" * cascade="all" * unique="true" */ public Address getAddress() {return address;} public void setAddress(Address address) {this.address = address;}}
· 需要改動的部分用斜體字標出來了,有兩處,一處是定義主鍵的生成方式,一處是Person類如何引用Address類。
· 看看Person類的映射文件中的相關部分:
<generator class="hilo">
<!--
To add non XDoclet generator parameters, create a file named
hibernate-generator-params-Person.xml
containing the additional parameters and place it in your merge dir.
-->
</generator>
<many-to-one
name="address"
class="javamxj.hibernate.association.one2one.Address"
cascade="all"
outer-join="auto"
update="true"
insert="true"
access="property"
column="fk_Address"
unique="true"
/>
· 注意:這里<many-to-one>上加上unique="true",表示限制一個Person有一個獨有的Address。
· 然后同上面文章一樣,生成映射文件,生成表,執(zhí)行Demo,最后數據表中生成如下數據:
· t_person表中多了一個fk_Address外鍵,這個外鍵將t_person表和t_address表一一對應起來了。