Hibernate 是成熟穩定的 ORM 框架,支援一對一、一對多、多對多等關聯映射。本文以 Hibernate 2.x 為基礎(概念適用於 3.x/5.x/6.x),示範從持久類別、XDoclet 產生映射檔、到 Ant 建構的完整流程。
POJO 需符合:預設建構子、私有欄位 + 公共 getter/setter、實作 Serializable(建議)。以 User 為例:
public class User {
private String userID;
private String userName;
private String password;
private String emailAddress;
private Date lastLogon;
private Set contacts; // 一對多
private Set books; // 多對多
private Address address; // 一對一
// getter/setter 略
}
/** @hibernate.class table="Users" */
public class User {
/** @hibernate.id generator-class="assigned" column="LogonID" type="string" */
public String getUserID() { return userID; }
/** @hibernate.property column="Name" type="string" */
public String getUserName() { return userName; }
/** @hibernate.one-to-one class="dbdemo.Address" */
public Address getAddress() { return address; }
/** @hibernate.set role="contacts" table="Contacts" cascade="all"
* @hibernate.collection-key column="User_ID"
* @hibernate.collection-one-to-many class="dbdemo.Contact" */
public Set getContacts() { return contacts; }
/** @hibernate.set role="books" table="Book_User_Link" cascade="all"
* @hibernate.collection-key column="UserID"
* @hibernate.collection-many-to-many class="dbdemo.Book" column="BookID" */
public Set getBooks() { return books; }
}
<project name="Hibernate Example" default="about" basedir=".">
<property name="xdoclet.lib.home" value="c:/java_api/xdoclet-1.2b3/lib"/>
<target name="hibernate" depends="prepare">
<taskdef name="hibernatedoclet" classname="xdoclet.modules.hibernate.HibernateDocletTask">
<classpath><fileset dir="${xdoclet.lib.home}"><include name="*.jar"/></fileset></classpath>
</taskdef>
<hibernatedoclet destdir="." excludedtags="@version,@author,@todo" force="true" verbose="true" mergedir="${dist}">
<fileset dir="."><include name="**/dbdemo/*.java"/></fileset>
<hibernate version="2.0"/>
</hibernatedoclet>
</target>
</project>
執行 ant hibernate 即產生 User.hbm.xml 等映射檔。
<class name="dbdemo.User" table="Users">
<id name="userID" column="LogonID" type="string">
<generator class="assigned"/>
</id>
<one-to-one name="address" class="dbdemo.Address" cascade="none" outer-join="auto"/>
<set name="books" table="Book_User_Link" lazy="false" inverse="true" cascade="all">
<key column="UserID"/>
<many-to-many class="dbdemo.Book" column="BookID"/>
</set>
<set name="contacts" table="Contacts" lazy="false" inverse="true" cascade="all">
<key column="User_ID"/>
<one-to-many class="dbdemo.Contact"/>
</set>
<property name="emailAddress" type="string" column="EmailAddress"/>
<property name="lastLogon" type="date" column="LastLogon"/>
<property name="password" type="string" column="Password"/>
<property name="userName" type="string" column="Name"/>
</class>
User ↔ Address,共享主鍵或外鍵唯一約束。User → Contact,Contacts 表有 User_ID 外鍵,inverse="true" 由多方維護關係。User ↔ Book,中間表 Book_User_Link,雙向 many-to-many,一方設 inverse="true"。// 查詢某用戶的所有書籍
from Book b join b.users u where u.userID = :uid
dialect 設 net.sf.hibernate.dialect.DB2Dialect;換資料庫只需改 dialect 與連線參數。@Entity, @OneToMany 等) 或 hibernate.cfg.xml,XDoclet 已淘汰。hibernate.hikari.* 設定。掌握映射檔結構有助於除錯與效能調校,即使現代專案多用註解,理解 XML 對應關係仍是核心功力。