接續 多對一 的內容,User對Room是多對一的關係,反過來Room對User就是一對多的關係,若要由Room來維持User的參考,則您可以如下設計:
- Room.java
package onlyfun.caterpillar;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
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.OneToMany;
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;
    @OneToMany(cascade=CascadeType.ALL)
    @JoinColumn(name="ROOM_ID_FK")
    private Set<User> users;
    public Set<User> getUsers() {
        return users;
    }
    public void setUsers(Set<User> users) {
        this.users = users;
    }
    public void addUser(User user) {
        users.add(user);
    }
    public void removeUser(User user) {
        users.remove(user);
    }
    // 以下為 Getter、Setter
    ....
}在這邊使用Set來維持對多個User實例的參考,而您的User可以如下設計:
- User.java
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_USER")
public class User implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="USER_ID")
    private Long id;
    private String name;
    private Long age;
    // 以下為 Getter、Setter
    ....
}一個儲存的例子如下所示,由於現在是由Room來維持對User的參考,所以直接儲存Room實例,User實例也會一併儲存:
User user1 = new User();
user1.setName("caterpillar");
user1.setAge(new Long(30));
User user2 = new User();
user2.setName("Justin");
user2.setAge(new Long(35));
Room room = new Room();
room.setUsers(new HashSet<User>());
room.setAddress("NTU-M8-419");
room.addUser(user1);
room.addUser(user2);
EntityManager entityManager =
JPAUtil.getEntityManagerFactory().createEntityManager();
EntityTransaction etx = entityManager.getTransaction();
etx.begin();
entityManager.persist(room);
etx.commit();
entityManager.close();
這個時候,有個效能上的議題可以探討,請參考 雙向關聯。
在查詢時,要注意的是,@OneToMany預設的Fetch模式是FetchType.LAZY,若您直接以下面的程式打算顯示User資訊:
EntityManager entityManager =
JPAUtil.getEntityManagerFactory().createEntityManager();
EntityTransaction etx = entityManager.getTransaction();
etx.begin();
room = entityManager.find(Room.class, new Long(1));
etx.commit();
entityManager.close();
System.out.println(room.getUsers());
FetchType.LAZY時,除非真正要使用到該屬性的值,否則不會真正將資料從表格中載入物件,所以上例中,由於EntityManager已經關閉,而此時若要再載入User,就會發生例外錯誤,解決的方式之一是在EntityManager關閉前取得資料。
EntityManager entityManager =
JPAUtil.getEntityManagerFactory().createEntityManager();
EntityTransaction etx = entityManager.getTransaction();
etx.begin();
room = entityManager.find(Room.class, new Long(1));
etx.commit();
System.out.println(room.getUsers());
entityManager.close();
或者是在@OneToMany上指定fetch屬性為FetchType.EAGER,表示一併載入所有屬性所對應的資料:
@OneToMany(cascade=CascadeType.ALL, mappedBy="room", fetch=FetchType.EAGER)
private Set<User> users;
關於Fetch模式的說明,還可以參考 CascadeType 與 FetchType。

