現在考慮每一個User配給一間Room,形成一對一,user表格透過room_id作為外鍵參考至room:
在表格建立方面,使用 多對一 中的表格建立語句就可以了:
create table room (
id bigint not null auto_increment,
address varchar(255),
primary key (id)
)
create table user (
id bigint not null auto_increment,
name varchar(255),
room_id bigint unique,
primary key (id)
)
id bigint not null auto_increment,
address varchar(255),
primary key (id)
)
create table user (
id bigint not null auto_increment,
name varchar(255),
room_id bigint unique,
primary key (id)
)
物件方面,User的實例會參考至Room實例,而Room實例也參考至User實例:
- User.java
package onlyfun.caterpillar;
public class User {
private Long id;
private String name;
private Room room;
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 Room getRoom() {
return room;
}
public void setRoom(Room room) {
this.room = room;
}
}
- Room.java
package onlyfun.caterpillar;
public class Room {
private Long id;
private String address;
private User user;
public Room() {}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
使用外鍵來完成一對一,其實就是限制多對一關係中,「多」的一方只能有一個參考至「一」的一方,也就是多對一關係的一個特例,這可以在映射文件中使用 <many-to-one>標籤時,加上"unique"屬性來設定,例如:
- 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>
<class name="onlyfun.caterpillar.User" table="user">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="name" column="name"/>
<many-to-one name="room"
column="room_id"
class="onlyfun.caterpillar.Room"
cascade="all"
outer-join="true"
unique="true"/>
</class>
</hibernate-mapping>
到這邊為止,單向一對一的映射已經完成,如果要再完成雙向一對一的關係,則可以在Room.hbm.xml中使用<one-to-one>標籤來定義:
- Room.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>
<class name="onlyfun.caterpillar.Room" table="room">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="address" column="address" />
<one-to-one name="user"
class="onlyfun.caterpillar.User"
property-ref="room"/>
</class>
</hibernate-mapping>
在<one-to-one>中,property-ref告訴Hibernate,查詢出user並將其參考至room。
一個儲存的例子如下:
User user1 = new User();
user1.setName("bush");
Room room1 = new Room();
room1.setAddress("NTU-M8-419");
user1.setRoom(room1);
User user2 = new User();
user2.setName("caterpillar");
Room room2 = new Room();
room2.setAddress("NTU-M8-418");
user2.setRoom(room2);
Session session = HibernateUti.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
session.save(user1);
session.save(user2);
tx.commit();
session.close();
user1.setName("bush");
Room room1 = new Room();
room1.setAddress("NTU-M8-419");
user1.setRoom(room1);
User user2 = new User();
user2.setName("caterpillar");
Room room2 = new Room();
room2.setAddress("NTU-M8-418");
user2.setRoom(room2);
Session session = HibernateUti.getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
session.save(user1);
session.save(user2);
tx.commit();
session.close();
在查詢Room時,User也會一載入,例如:
Session
session = HibernateUtil.getSessionFactory().openSession();
Room room = (Room) session.load(Room.class, new Long(23));
System.out.println(room.getUser().getName());
session.close();
Room room = (Room) session.load(Room.class, new Long(23));
System.out.println(room.getUser().getName());
session.close();
上面的查詢程式,Hibernate將使用以下的SQL:
Hibernate:
select
room0_.id as id1_1_,
room0_.address as address1_1_,
user1_.id as id0_0_,
user1_.name as name0_0_,
user1_.room_id as room3_0_0_
from
room room0_
left outer join
user user1_
on room0_.id=user1_.room_id
where
room0_.id=?
select
room0_.id as id1_1_,
room0_.address as address1_1_,
user1_.id as id0_0_,
user1_.name as name0_0_,
user1_.room_id as room3_0_0_
from
room room0_
left outer join
user user1_
on room0_.id=user1_.room_id
where
room0_.id=?