|
|
接續 多對一 的內容,User對Room是多對一的關係,反過來Room對User就是一對多的關係,若要由Room來維持User的參考,則您可以如下設計:
package onlyfun.caterpillar; 在這邊使用Set來維持對多個User實例的參考,而您的User可以如下設計:
package onlyfun.caterpillar; 一個儲存的例子如下所示,由於現在是由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。 |