考慮每一個User配給一間Room,形成一對一,T_USER表格透過USER_ROOM_ID作為外鍵參考至T_ROOM的ROOM_ID:

物件方面,可設計User的實例參考至Room實例,而希望儲存User實例時,若有參考至Room實例,Room實例也一併儲存。
您可以如下設計User類別:
package onlyfun.caterpillar;
import java.io.Serializable; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToOne; import javax.persistence.Table;
@Entity @Table(name="T_USER") public class User implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name="USER_ID") private Long id; private String name; private Long age;
@OneToOne(cascade=CascadeType.ALL) @JoinColumn(name="USER_ROOM_ID", referencedColumnName="ROOM_ID") private Room room;
public Long getAge() { return age; } public void setAge(Long age) { this.age = age; }
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; } }
從上面可以看到,您使用@OneToOne來標註一對一實體關聯,而cascade設定為CascadeType.ALL,表示儲存User實例時,若有參考至Room實例,Room實例也一併儲存,這個稱之為聯級(Cascade)操作,設定為ALL,表示之後修改、刪除等動作,也會一併更新Room的對應表格資料。
關於Fetch模式的說明,還可以參考 CascadeType 與 FetchType。
@JoinColumn中設定T_USER表格透過USER_ROOM_ID作為外鍵參考至T_ROOM的ROOM_ID。
Room類別的設計可以如下所示:
package onlyfun.caterpillar;
import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table;
@Entity @Table(name="T_ROOM") public class Room implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name="ROOM_ID") private Long id; private String address;
public String getAddress() { return address; } public void setAddress(String address) { this.address = address; }
public Long getId() { return id; } public void setId(Long id) { this.id = id; } }
一個儲存的例子如下所示,由於設定了聯級操作為ALL,所以只要儲存User,所參考的Room也會一併儲存:
Room room = new Room();
room.setAddress("NTU-M8-419");
User user = new User();
user.setName("caterpillar");
user.setAge(new Long(30));
user.setRoom(room);
EntityManager entityManager =
JPAUtil.getEntityManagerFactory().createEntityManager();
EntityTransaction etx = entityManager.getTransaction();
etx.begin();
entityManager.persist(user);
etx.commit();
entityManager.close();
儲存時會先儲存Room的資料,取得ROOM_ID之後,再儲存User的資料,例如以Hibernate作為JPA的實作,會產生以下的SQL語句:
Hibernate:
insert
into
T_ROOM
(address)
values
(?)
Hibernate:
insert
into
T_USER
(age, name, USER_ROOM_ID)
values
(?, ?, ?)
一個儲存時的資料表內容範例如下:

而查詢時,會使用LEFT OUTER JOIN的方式結合表格進行查詢,例如以下的陳述:
User user = entityManager.find(User.class, new Long(1));
以Hibernate作為JPA的實作,會產生以下的SQL語句:
Hibernate:
select
user0_.USER_ID as USER1_0_1_,
user0_.age as age0_1_,
user0_.name as name0_1_,
user0_.USER_ROOM_ID as USER4_0_1_,
room1_.ROOM_ID as ROOM1_1_0_,
room1_.address as address1_0_
from
T_USER user0_
left outer join
T_ROOM room1_
on user0_.USER_ROOM_ID=room1_.ROOM_ID
where
user0_.USER_ID=?
|