User對Room是多對一的關系,那么反過來Room對User就是一對多的關系了。

User.java:

  1. package com.hb3.pack_17.model;

  2. public class User {

  3.     private Integer id;
  4.     private String name;
  5.     
  6.     public User() {
  7.     }

  8.     public Integer getId() {
  9.         return id;
  10.     }
  11.     public void setId(Integer id) {
  12.         this.id = id;
  13.     }
  14.     public String getName() {
  15.         return name;
  16.     }
  17.     public void setName(String name) {
  18.         this.name = name;
  19.     }
  20. }

Room.java:

  1. package com.hb3.pack_17.model;

  2. import java.util.Set;

  3. public class Room {

  4.     private Integer id; 
  5.     private String address;
  6.     private Set<User> users;
  7.     
  8.     public Room() {
  9.     }
  10.     
  11.     public Integer getId() { 
  12.         return id; 
  13.     } 
  14.     public void setId(Integer id) { 
  15.         this.id = id; 
  16.     }
  17.     public String getAddress() { 
  18.         return address; 
  19.     }
  20.     public void setAddress(String address) { 
  21.         this.address = address; 
  22.     }
  23.     public Set<User> getUsers() {
  24.         return users;
  25.     }
  26.     public void setUsers(Set<User> users) {
  27.         this.users = users;
  28.     }
  29.     public void addUser(User user) {
  30.         users.add(user);        
  31.     }
  32.     public void removeUser(User user) {
  33.         users.remove(user);
  34.     }
  35. }

Room.hbm.xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE hibernate-mapping 
  3.     PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
  4.     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

  5. <hibernate-mapping>

  6.     <class name="com.hb3.pack_17.model.Room" table="room"> 
  7.     
  8.         <id name="id" column="id"> 
  9.             <generator class="native"/> 
  10.         </id> 
  11.         
  12.         <property name="address" 
  13.                   column="address" 
  14.                   type="java.lang.String"/> 
  15.                   
  16.         <set name="users" table="user" cascade="all">
  17.             <key column="room_id"/>
  18.             <one-to-many class="com.hb3.pack_17.model.User"/>
  19.         </set>
  20.         
  21.     </class> 
  22. </hibernate-mapping>

User.hbm.xml:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE hibernate-mapping 
  3.     PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
  4.     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

  5. <hibernate-mapping> 

  6.     <class name="com.hb3.pack_17.model.User" table="user">
  7.     
  8.         <id name="id" column="id" type="java.lang.Integer"> 
  9.             <generator class="native"/> 
  10.         </id> 

  11.         <property name="name" column="name" type="java.lang.String"/> 
  12.         
  13.     </class> 

  14. </hibernate-mapping>

測試代碼:

  1. package com.hb3.pack_17;

  2. import java.io.IOException;
  3. import java.sql.SQLException;
  4. import java.util.HashSet;

  5. import org.hibernate.Session;
  6. import org.hibernate.SessionFactory;
  7. import org.hibernate.Transaction;
  8. import org.hibernate.cfg.Configuration;

  9. import com.hb3.pack_17.model.Room;
  10. import com.hb3.pack_17.model.User;


  11. public class BusinessService {

  12.     public static void main(String[] args) throws IOException, SQLException {
  13.         
  14.         Configuration config = new Configuration().configure();
  15.         SessionFactory sessionFactory = config.buildSessionFactory();      
  16.         Session session = sessionFactory.openSession();

  17.         
  18.         User user1 = new User();
  19.         user1.setName("yangye");      
  20.         User user2 = new User(); 
  21.         user2.setName("shenbin");       
  22.         User user3 = new User(); 
  23.         user3.setName("chenyan"); 

  24.         Room room1 = new Room(); 
  25.         room1.setUsers(new HashSet<User>());
  26.         room1.setAddress("NTU-M8-419");
  27.         room1.addUser(user1);
  28.         room1.addUser(user2);   
  29.         Room room2 = new Room();
  30.         room2.setUsers(new HashSet<User>());
  31.         room2.setAddress("NTU-G3-302");
  32.         room2.addUser(user3);
  33.                 
  34.         Transaction tx = session.beginTransaction();   
  35.         session.save(room1);
  36.         session.save(room2);    
  37.         tx.commit();

  38.         
  39.         session.close();
  40.         sessionFactory.close();
  41.     }
  42. }

雙向關聯:

以上多對一,一對多的關系都是單向關聯,也就是一方聯系到另一方,而另一方不知道自己被關聯。

如果上方都意識到另一方的存在,則形成雙向關聯。現將上面的代碼改寫如下:

在User類中追加Room類型的字段:

  1. package com.hb3.pack_20.model;

  2. public class User {

  3.     private Integer id;
  4.     private String name;
  5.     private Room room;
  6.     
  7.     public Room getRoom() {
  8.         return room;
  9.     }

  10.     public void setRoom(Room room) {
  11.         this.room = room;
  12.     }

  13.     public User() {
  14.     }

  15.     public Integer getId() {
  16.         return id;
  17.     }
  18.     public void setId(Integer id) {
  19.         this.id = id;
  20.     }
  21.     public String getName() {
  22.         return name;
  23.     }
  24.     public void setName(String name) {
  25.         this.name = name;
  26.     }
  27. }

User.hbm.xml中也同樣追加關于Room的信息:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE hibernate-mapping 
  3.     PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
  4.     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

  5. <hibernate-mapping> 

  6.     <class name="com.hb3.pack_20.model.User" table="user">
  7.     
  8.         <id name="id" column="id" type="java.lang.Integer"> 
  9.             <generator class="native"/> 
  10.         </id> 

  11.         <property name="name" column="name" type="java.lang.String"/> 
  12.         
  13.         <many-to-one name="room" 
  14.                      column="room_id" 
  15.                      class="com.hb3.pack_20.model.Room"
  16.                      cascade="save-update"
  17.                      outer-join="true"/> 
  18.         
  19.     </class> 

  20. </hibernate-mapping>

這里我們將Room.hbm.xml文件里set的cascade屬性也設為save-update

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE hibernate-mapping 
  3.     PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
  4.     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

  5. <hibernate-mapping>

  6.     <class name="com.hb3.pack_20.model.Room" table="room"> 
  7.     
  8.         <id name="id" column="id"> 
  9.             <generator class="native"/> 
  10.         </id> 
  11.         
  12.         <property name="address" 
  13.                   column="address" 
  14.                   type="java.lang.String"/> 
  15.                   
  16.         <set name="users" table="user" cascade="save-update">
  17.             <key column="room_id"/>
  18.             <one-to-many class="com.hb3.pack_20.model.User"/>
  19.         </set>
  20.         
  21.     </class> 
  22. </hibernate-mapping>

這樣我們可以用多對一的方式來維持管理:

  1. package com.hb3.pack_20;

  2. import org.hibernate.Session;
  3. import org.hibernate.SessionFactory;
  4. import org.hibernate.Transaction;
  5. import org.hibernate.cfg.Configuration;

  6. import com.hb3.pack_20.model.Room;
  7. import com.hb3.pack_20.model.User;

  8. public class BusinessService {

  9.     public static void main(String[] args) {
  10.         
  11.         Configuration config = new Configuration().configure();
  12.         SessionFactory sessionFactory = config.buildSessionFactory();      
  13.         Session session = sessionFactory.openSession();

  14.         
  15.         User user1 = new User();
  16.         user1.setName("chenyan"); 
  17.                 
  18.         User user2 = new User(); 
  19.         user2.setName("shenbin"); 

  20.         Room room1 = new Room(); 
  21.         room1.setAddress("NTU-M8-419");

  22.         user1.setRoom(room1);
  23.         user2.setRoom(room1);
  24.                 
  25.         Transaction tx = session.beginTransaction();     
  26.         session.save(user1);
  27.         session.save(user2);
  28.         tx.commit();


  29.         session.close();
  30.         sessionFactory.close();
  31.     }
  32. }

或者反過來由一對多的方式來維持關系:

  1. package com.hb3.pack_20;

  2. import java.util.HashSet;

  3. import org.hibernate.Session;
  4. import org.hibernate.SessionFactory;
  5. import org.hibernate.Transaction;
  6. import org.hibernate.cfg.Configuration;

  7. import com.hb3.pack_20.model.Room;
  8. import com.hb3.pack_20.model.User;

  9. public class BusinessService {

  10.     public static void main(String[] args) {
  11.         
  12.         Configuration config = new Configuration().configure();
  13.         SessionFactory sessionFactory = config.buildSessionFactory();      
  14.         Session session = sessionFactory.openSession();

  15.         
  16.         User user1 = new User();
  17.         user1.setName("chenyan"); 
  18.                 
  19.         User user2 = new User(); 
  20.         user2.setName("shenbin"); 

  21.         Room room1 = new Room(); 
  22.         room1.setUsers(new HashSet<User>());
  23.         room1.setAddress("NTU-M8-419");
  24.         room1.addUser(user1);
  25.         room1.addUser(user2);
  26.                 
  27.         Transaction tx = session.beginTransaction();  
  28.         session.save(room1); 
  29.         tx.commit();


  30.         session.close();
  31.         sessionFactory.close();
  32.     }
  33. }

但是一對多的方式來維持的話,先看一下生成的SQL文:

Hibernate: insert into room (address) values (?)
Hibernate: insert into user (name, room_id) values (?, ?)
Hibernate: insert into user (name, room_id) values (?, ?)
Hibernate: update user set room_id=? where id=?
Hibernate: update user set room_id=? where id=?

 

可見,如果把一的一方Room作為主控方,多的一方User因為不知道Room的room_id是多少,所以 必須等Room和User存儲之后再更新room_id。所以在多對一,一對多形成雙向關聯的時候,應該把控制權交給多的一方,這樣比較有效率。理由很簡 單,就像在公司里一樣,老板記住所有員工的名字來得快,還是每個員工記住老板的名字來得快。

 

基于這個理由,我們對Room.hbm.xml再稍作修改:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE hibernate-mapping 
  3.     PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
  4.     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

  5. <hibernate-mapping>

  6.     <class name="com.hb3.pack_20.model.Room" table="room"> 
  7.     
  8.         <id name="id" column="id"> 
  9.             <generator class="native"/> 
  10.         </id> 
  11.         
  12.         <property name="address" 
  13.                   column="address" 
  14.                   type="java.lang.String"/> 
  15.                   
  16.         <set name="users" table="user" cascade="save-update" inverse="true">
  17.             <key column="room_id"/>
  18.             <one-to-many class="com.hb3.pack_20.model.User"/>
  19.         </set>
  20.         
  21.     </class> 
  22. </hibernate-mapping>

如此控制權就交給了多的一方。當直接存儲一的一方前,必須讓多的一方意識的一的一方的存在。

  1. package com.hb3.pack_20;

  2. import java.io.IOException;
  3. import java.sql.SQLException;
  4. import java.util.HashSet;

  5. import org.hibernate.Session;
  6. import org.hibernate.SessionFactory;
  7. import org.hibernate.Transaction;
  8. import org.hibernate.cfg.Configuration;

  9. import com.hb3.pack_20.model.Room;
  10. import com.hb3.pack_20.model.User;

  11. public class BusinessService {

  12.     public static void main(String[] args) throws IOException, SQLException {
  13.         
  14.         Configuration config = new Configuration().configure();
  15.         SessionFactory sessionFactory = config.buildSessionFactory();      
  16.         Session session = sessionFactory.openSession();

  17.         
  18.         User user1 = new User();
  19.         user1.setName("bush"); 
  20.                 
  21.         User user2 = new User(); 
  22.         user2.setName("caterpillar"); 

  23.         Room room1 = new Room(); 
  24.         room1.setUsers(new HashSet<User>());
  25.         room1.setAddress("NTU-M8-419");
  26.         room1.addUser(user1);
  27.         room1.addUser(user2);

  28.         //多方必須認識到單方的存在
  29.         user1.setRoom(room1);
  30.         user2.setRoom(room1);
  31.                 
  32.         Transaction tx = session.beginTransaction();     
  33.         session.save(room1); 
  34.         tx.commit();


  35.         session.close();
  36.         sessionFactory.close();
  37.     }
  38. }

此時生成的SQL文為:

Hibernate: insert into room (address) values (?)
Hibernate: insert into user (name, room_id) values (?, ?)
Hibernate: insert into user (name, room_id) values (?, ?)

從而提高了效率。

 

如果把代碼中user1.setRoom(room1);和user2.setRoom(room1);這2 行移去,你會發現數據庫中room_id的值為null。這個結果就好比在多對一的關系中沒有分配給User一個Room,那么理所當然room_id的 值為null了。



ExtJS教程- Hibernate教程-Struts2 教程-Lucene教程