假設您設計了這麼一個user表格:
create table T_USER (
id integer not null auto_increment,
name varchar(255),
age integer,
email varchar(255) not null,
primary key (id)
)
id integer not null auto_increment,
name varchar(255),
age integer,
email varchar(255) not null,
primary key (id)
)
最基本的映射策略中,您可以設計一個如下的User類別與之對應:
package
onlyfun.caterpillar;
public class User {
private Long id;
private String name;
private int age;
private String email;
........
}
public class User {
private Long id;
private String name;
private int age;
private String email;
........
}
現在假設您基於業務上的設計需求,您需要將email資訊提昇為一個MailAddress物件,讓它攜帶更多資訊或負有特定職責,例如:
- MailAddress.java
package onlyfun.caterpillar;
public class MailAddress {
private String email;
public MailAddress() {}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public void sendMail() {
System.out.println("Send mail to " + email);
}
}
而User類別中有(has a)MailAddress,例如:
- User.java
package onlyfun.caterpillar;
public class User {
private Long id;
private String name;
private Long age;
private MailAddress mailAddress;
// 必須要有一個預設的建構方法
// 以使得Hibernate可以使用Constructor.newInstance()建立物件
public User() {}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getAge() {
return age;
}
public void setAge(Long age) {
this.age = age;
}
public MailAddress getMailAddress() {
return mailAddress;
}
public void setMailAddress(MailAddress mailAddress) {
this.mailAddress = mailAddress;
}
}
像MailAddress這樣的物件稱之為值類型(value type)物件,它沒有自己的識別(identity),通常隸屬於一個實體物件,其生命週期跟隨著所隸屬的實體物件,值類型物件通常不會共用。
在資料庫表格方面並沒有任何的改變,這是基於程式設計上的考量,增加物件設計上的粒度,MailAddress為User的一個Component,在映 射文件上,您可以使用<component>標籤來完成這樣的映射:
- User.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="onlyfun.caterpillar">
<class name="User" table="T_USER">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="name" column="name" />
<property name="age" column="age" />
<component name="mailAddress" class="MailAddress">
<property name="email" column="email" not-null="true"/>
</component>
</class>
</hibernate-mapping>
在物件儲存時的一個示範如下:
MailAddress
mailAddress = new MailAddress();
mailAddress.setEmail("caterpillar.onlyfun@gmail.com");
User user = new User();
user.setName("caterpillar");
user.setAge(new Long(30));
user.setMailAddress(mailAddress);
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
session.save(user);
tx.commit();
session.close();
mailAddress.setEmail("caterpillar.onlyfun@gmail.com");
User user = new User();
user.setName("caterpillar");
user.setAge(new Long(30));
user.setMailAddress(mailAddress);
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
session.save(user);
tx.commit();
session.close();
在物件查詢與使用上的一個例子如下:
Session
session = HibernateUtil.getSessionFactory().openSession();
User user = (User) session.load(User.class, new Long(1));
System.out.println(user.getAge() + "\t" +
user.getName() + "\t" +
user.getMailAddress().getEmail());
user.getMailAddress().sendMail();
session.close();
User user = (User) session.load(User.class, new Long(1));
System.out.println(user.getAge() + "\t" +
user.getName() + "\t" +
user.getMailAddress().getEmail());
user.getMailAddress().sendMail();
session.close();
以上所建立的是單向的關係,只能從User到MailAddress的關係,Hibernate允許您建立雙向關係,也就是從MailAddress的關係,您可以在MailAddress上新增User類型的屬性,然後在映射檔案中設定<parent>:
<component name="mailAddress" class="MailAddress">
<parent name="user"/>
<property name="email" column="email" not-null="true"/>
</component>
<parent name="user"/>
<property name="email" column="email" not-null="true"/>
</component>
如此一來,當透過user查詢到MailAddress時,Hibernate會自動加上user實例的參考,也就是您可以如下取得user實例:
mailAddress.getUser();
必要的話,可以再將粒度細化,也就是<component>中還可以再設定<component>。