接上例:http://blog.csdn.net/kunshan_shenbin/archive/2008/09/03/2873943.aspx
User对Room是多对一的关系,那么反过来Room对User就是一对多的关系了。
User.java:
1.package com.hb3.pack_17.model;<br />2.<br />3.public class User {<br />4.5. private Integer id;<br />6. private String name;<br />7.<br />8. public User() {<br />9. }<br />10.11. public Integer getId() {<br />12. return id;<br />13. }<br />14. public void setId(Integer id) {<br />15. this.id = id;<br />16. }<br />17. public String getName() {<br />18. return name;<br />19. }<br />20. public void setName(String name) {<br />21. this.name = name;<br />22. }<br />23.}
Room.java:
1.package com.hb3.pack_17.model;<br />2.<br />3.import java.util.Set;<br />4.5.public class Room {<br />6.7. private Integer id;<br />8. private String address;<br />9. private Set<User> users;<br />10.<br />11. public Room() {<br />12. }<br />13.<br />14. public Integer getId() { <br />15. return id;<br />16. } <br />17. public void setId(Integer id) { <br />18. this.id = id;<br />19. }<br />20. public String getAddress() { <br />21. return address;<br />22. }<br />23. public void setAddress(String address) { <br />24. this.address = address;<br />25. }<br />26. public Set<User> getUsers() {<br />27. return users;<br />28. }<br />29. public void setUsers(Set<User> users) {<br />30. this.users = users;<br />31. }<br />32. public void addUser(User user) {<br />33. users.add(user);<br />34. }<br />35. public void removeUser(User user) {<br />36. users.remove(user);<br />37. }<br />38.}
Room.hbm.xml:
1.<?xml version="1.0" encoding="utf-8"?><br />2.<!DOCTYPE hibernate-mapping<br />3. PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"<br />4. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">5.6.<hibernate-mapping>7.8. <class name="com.hb3.pack_17.model.Room" table="room"><br />9.<br />10. <id name="id" column="id"><br />11. <generator class="native"/><br />12. </id><br />13.<br />14. <property name="address"<br />15. column="address"<br />16. type="java.lang.String"/><br />17.<br />18. <set name="users" table="user" cascade="all">19. <key column="room_id"/>20. <one-to-many class="com.hb3.pack_17.model.User"/>21. </set>22.<br />23. </class><br />24.</hibernate-mapping>
User.hbm.xml:
1.<?xml version="1.0" encoding="utf-8"?><br />2.<!DOCTYPE hibernate-mapping<br />3. PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"<br />4. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">5.6.<hibernate-mapping><br />7.8. <class name="com.hb3.pack_17.model.User" table="user">9.<br />10. <id name="id" column="id" type="java.lang.Integer"><br />11. <generator class="native"/><br />12. </id><br />13.14. <property name="name" column="name" type="java.lang.String"/><br />15.<br />16. </class><br />17.18.</hibernate-mapping>
测试代码:
1.package com.hb3.pack_17;<br />2.<br />3.import java.io.IOException;<br />4.import java.sql.SQLException;<br />5.import java.util.HashSet;<br />6.7.import org.hibernate.Session;<br />8.import org.hibernate.SessionFactory;<br />9.import org.hibernate.Transaction;<br />10.import org.hibernate.cfg.Configuration;<br />11.12.import com.hb3.pack_17.model.Room;<br />13.import com.hb3.pack_17.model.User;<br />14.15.16.public class BusinessService {<br />17.18. public static void main(String[] args) throws IOException, SQLException {<br />19.<br />20. Configuration config = new Configuration().configure();<br />21. SessionFactory sessionFactory = config.buildSessionFactory();<br />22. Session session = sessionFactory.openSession();<br />23.24.<br />25. User user1 = new User();<br />26. user1.setName("yangye");<br />27. User user2 = new User();<br />28. user2.setName("shenbin");<br />29. User user3 = new User();<br />30. user3.setName("chenyan");<br />31.32. Room room1 = new Room();<br />33. room1.setUsers(new HashSet<User>());<br />34. room1.setAddress("NTU-M8-419");<br />35. room1.addUser(user1);<br />36. room1.addUser(user2);<br />37. Room room2 = new Room();<br />38. room2.setUsers(new HashSet<User>());<br />39. room2.setAddress("NTU-G3-302");<br />40. room2.addUser(user3);<br />41.<br />42. Transaction tx = session.beginTransaction();<br />43. session.save(room1);<br />44. session.save(room2);<br />45. tx.commit();<br />46.47.<br />48. session.close();<br />49. sessionFactory.close();<br />50. }<br />51.}
双向关联:
以上多对一,一对多的关系都是单向关联,也就是一方联系到另一方,而另一方不知道自己被关联。
如果上方都意识到另一方的存在,则形成双向关联。现将上面的代码改写如下:
在User类中追加Room类型的字段:
1.package com.hb3.pack_20.model;<br />2.<br />3.public class User {<br />4.5. private Integer id;<br />6. private String name;<br />7. private Room room;<br />8.<br />9. public Room getRoom() {<br />10. return room;<br />11. }<br />12.13. public void setRoom(Room room) {<br />14. this.room = room;<br />15. }<br />16.17. public User() {<br />18. }<br />19.20. public Integer getId() {<br />21. return id;<br />22. }<br />23. public void setId(Integer id) {<br />24. this.id = id;<br />25. }<br />26. public String getName() {<br />27. return name;<br />28. }<br />29. public void setName(String name) {<br />30. this.name = name;<br />31. }<br />32.}
User.hbm.xml中也同样追加关于Room的信息:
1.<?xml version="1.0" encoding="utf-8"?><br />2.<!DOCTYPE hibernate-mapping<br />3. PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"<br />4. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">5.6.<hibernate-mapping><br />7.8. <class name="com.hb3.pack_20.model.User" table="user">9.<br />10. <id name="id" column="id" type="java.lang.Integer"><br />11. <generator class="native"/><br />12. </id><br />13.14. <property name="name" column="name" type="java.lang.String"/><br />15.<br />16. <many-to-one name="room"<br />17. column="room_id"<br />18. class="com.hb3.pack_20.model.Room"19. cascade="save-update"20. outer-join="true"/><br />21.<br />22. </class><br />23.<br />24.</hibernate-mapping>
这里我们将Room.hbm.xml文件里set的cascade属性也设为save-update:
1.<?xml version="1.0" encoding="utf-8"?><br />2.<!DOCTYPE hibernate-mapping<br />3. PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"<br />4. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">5.6.<hibernate-mapping>7.8. <class name="com.hb3.pack_20.model.Room" table="room"><br />9.<br />10. <id name="id" column="id"><br />11. <generator class="native"/><br />12. </id><br />13.<br />14. <property name="address"<br />15. column="address"<br />16. type="java.lang.String"/><br />17.<br />18. <set name="users" table="user" cascade="save-update">19. <key column="room_id"/>20. <one-to-many class="com.hb3.pack_20.model.User"/>21. </set>22.<br />23. </class><br />24.</hibernate-mapping>
这样我们可以用多对一的方式来维持管理:
1.package com.hb3.pack_20;<br />2.<br />3.import org.hibernate.Session;<br />4.import org.hibernate.SessionFactory;<br />5.import org.hibernate.Transaction;<br />6.import org.hibernate.cfg.Configuration;<br />7.8.import com.hb3.pack_20.model.Room;<br />9.import com.hb3.pack_20.model.User;<br />10.11.public class BusinessService {<br />12.13. public static void main(String[] args) {<br />14.<br />15. Configuration config = new Configuration().configure();<br />16. SessionFactory sessionFactory = config.buildSessionFactory();<br />17. Session session = sessionFactory.openSession();<br />18.19.<br />20. User user1 = new User();<br />21. user1.setName("chenyan");<br />22.<br />23. User user2 = new User();<br />24. user2.setName("shenbin");<br />25.26. Room room1 = new Room();<br />27. room1.setAddress("NTU-M8-419");<br />28.29. user1.setRoom(room1);<br />30. user2.setRoom(room1);<br />31.<br />32. Transaction tx = session.beginTransaction();<br />33. session.save(user1);<br />34. session.save(user2);<br />35. tx.commit();<br />36.37.38. session.close();<br />39. sessionFactory.close();<br />40. }<br />41.}
或者反过来由一对多的方式来维持关系:
1.package com.hb3.pack_20;<br />2.<br />3.import java.util.HashSet;<br />4.5.import org.hibernate.Session;<br />6.import org.hibernate.SessionFactory;<br />7.import org.hibernate.Transaction;<br />8.import org.hibernate.cfg.Configuration;<br />9.10.import com.hb3.pack_20.model.Room;<br />11.import com.hb3.pack_20.model.User;<br />12.13.public class BusinessService {<br />14.15. public static void main(String[] args) {<br />16.<br />17. Configuration config = new Configuration().configure();<br />18. SessionFactory sessionFactory = config.buildSessionFactory();<br />19. Session session = sessionFactory.openSession();<br />20.21.<br />22. User user1 = new User();<br />23. user1.setName("chenyan");<br />24.<br />25. User user2 = new User();<br />26. user2.setName("shenbin");<br />27.28. Room room1 = new Room();<br />29. room1.setUsers(new HashSet<User>());<br />30. room1.setAddress("NTU-M8-419");<br />31. room1.addUser(user1);<br />32. room1.addUser(user2);<br />33.<br />34. Transaction tx = session.beginTransaction();<br />35. session.save(room1);<br />36. tx.commit();<br />37.38.<br />39. session.close();<br />40. sessionFactory.close();<br />41. }<br />42.}
但是一对多的方式来维持的话,先看一下生成的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"?><br />2.<!DOCTYPE hibernate-mapping<br />3. PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"<br />4. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">5.6.<hibernate-mapping>7.8. <class name="com.hb3.pack_20.model.Room" table="room"><br />9.<br />10. <id name="id" column="id"><br />11. <generator class="native"/><br />12. </id><br />13.<br />14. <property name="address"<br />15. column="address"<br />16. type="java.lang.String"/><br />17.<br />18. <set name="users" table="user" cascade="save-update" inverse="true">19. <key column="room_id"/>20. <one-to-many class="com.hb3.pack_20.model.User"/>21. </set>22.<br />23. </class><br />24.</hibernate-mapping>
如此控制权就交给了多的一方。当直接存储一的一方前,必须让多的一方意识的一的一方的存在。
1.package com.hb3.pack_20;<br />2.<br />3.import java.io.IOException;<br />4.import java.sql.SQLException;<br />5.import java.util.HashSet;<br />6.7.import org.hibernate.Session;<br />8.import org.hibernate.SessionFactory;<br />9.import org.hibernate.Transaction;<br />10.import org.hibernate.cfg.Configuration;<br />11.12.import com.hb3.pack_20.model.Room;<br />13.import com.hb3.pack_20.model.User;<br />14.15.public class BusinessService {<br />16.17. public static void main(String[] args) throws IOException, SQLException {<br />18.<br />19. Configuration config = new Configuration().configure();<br />20. SessionFactory sessionFactory = config.buildSessionFactory();<br />21. Session session = sessionFactory.openSession();<br />22.23.<br />24. User user1 = new User();<br />25. user1.setName("bush");<br />26.<br />27. User user2 = new User();<br />28. user2.setName("caterpillar");<br />29.30. Room room1 = new Room();<br />31. room1.setUsers(new HashSet<User>());<br />32. room1.setAddress("NTU-M8-419");<br />33. room1.addUser(user1);<br />34. room1.addUser(user2);<br />35.36. //多方必须认识到单方的存在37. user1.setRoom(room1);<br />38. user2.setRoom(room1);<br />39.<br />40. Transaction tx = session.beginTransaction();<br />41. session.save(room1);<br />42. tx.commit();<br />43.44.45. session.close();<br />46. sessionFactory.close();<br />47. }<br />48.}
此时生成的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了。
生命不息,奋斗不止,就像我们常说的一句话;