- <?xml version="1.0" encoding="utf-8"?>
- <!DOCTYPE hibernate-mapping
- PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping>
- <class name="com.hb3.pack_20.model.User" table="user">
-
- <id name="id" column="id" type="java.lang.Integer">
- <generator class="native"/>
- </id>
- <property name="name" column="name" type="java.lang.String"/>
-
- <many-to-one name="room"
- column="room_id"
- class="com.hb3.pack_20.model.Room"
- cascade="save-update"
- outer-join="true"/>
-
- </class>
- </hibernate-mapping>
这里我们将Room.hbm.xml文件里set的cascade属性也设为save-update:
- <?xml version="1.0" encoding="utf-8"?>
- <!DOCTYPE hibernate-mapping
- PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping>
- <class name="com.hb3.pack_20.model.Room" table="room">
-
- <id name="id" column="id">
- <generator class="native"/>
- </id>
-
- <property name="address"
- column="address"
- type="java.lang.String"/>
-
- <set name="users" table="user" cascade="save-update">
- <key column="room_id"/>
- <one-to-many class="com.hb3.pack_20.model.User"/>
- </set>
-
- </class>
- </hibernate-mapping>
这样我们可以用多对一的方式来维持管理:
- package com.hb3.pack_20;
- import org.hibernate.Session;
- import org.hibernate.SessionFactory;
- import org.hibernate.Transaction;
- import org.hibernate.cfg.Configuration;
- import com.hb3.pack_20.model.Room;
- import com.hb3.pack_20.model.User;
- public class BusinessService {
- public static void main(String[] args) {
-
- Configuration config = new Configuration().configure();
- SessionFactory sessionFactory = config.buildSessionFactory();
- Session session = sessionFactory.openSession();
-
- User user1 = new User();
- user1.setName("chenyan");
-
- User user2 = new User();
- user2.setName("shenbin");
- Room room1 = new Room();
- room1.setAddress("NTU-M8-419");
- user1.setRoom(room1);
- user2.setRoom(room1);
-
- Transaction tx = session.beginTransaction();
- session.save(user1);
- session.save(user2);
- tx.commit();
- session.close();
- sessionFactory.close();
- }
- }
或者反过来由一对多的方式来维持关系:
- package com.hb3.pack_20;
- import java.util.HashSet;
- import org.hibernate.Session;
- import org.hibernate.SessionFactory;
- import org.hibernate.Transaction;
- import org.hibernate.cfg.Configuration;
- import com.hb3.pack_20.model.Room;
- import com.hb3.pack_20.model.User;
- public class BusinessService {
- public static void main(String[] args) {
-
- Configuration config = new Configuration().configure();
- SessionFactory sessionFactory = config.buildSessionFactory();
- Session session = sessionFactory.openSession();
-
- User user1 = new User();
- user1.setName("chenyan");
-
- User user2 = new User();
- user2.setName("shenbin");
- Room room1 = new Room();
- room1.setUsers(new HashSet<User>());
- room1.setAddress("NTU-M8-419");
- room1.addUser(user1);
- room1.addUser(user2);
-
- Transaction tx = session.beginTransaction();
- session.save(room1);
- tx.commit();
- session.close();
- sessionFactory.close();
- }
- }
但是一对多的方式来维持的话,先看一下生成的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再稍作修改:
- <?xml version="1.0" encoding="utf-8"?>
- <!DOCTYPE hibernate-mapping
- PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping>
- <class name="com.hb3.pack_20.model.Room" table="room">
-
- <id name="id" column="id">
- <generator class="native"/>
- </id>
-
- <property name="address"
- column="address"
- type="java.lang.String"/>
-
- <set name="users" table="user" cascade="save-update" inverse="true">
- <key column="room_id"/>
- <one-to-many class="com.hb3.pack_20.model.User"/>
- </set>
-
- </class>
- </hibernate-mapping>
如此控制权就交给了多的一方。当直接存储一的一方前,必须让多的一方意识的一的一方的存在。
- package com.hb3.pack_20;
- import java.io.IOException;
- import java.sql.SQLException;
- import java.util.HashSet;
- import org.hibernate.Session;
- import org.hibernate.SessionFactory;
- import org.hibernate.Transaction;
- import org.hibernate.cfg.Configuration;
- import com.hb3.pack_20.model.Room;
- import com.hb3.pack_20.model.User;
- public class BusinessService {
- public static void main(String[] args) throws IOException, SQLException {
-
- Configuration config = new Configuration().configure();
- SessionFactory sessionFactory = config.buildSessionFactory();
- Session session = sessionFactory.openSession();
-
- User user1 = new User();
- user1.setName("bush");
-
- User user2 = new User();
- user2.setName("caterpillar");
- Room room1 = new Room();
- room1.setUsers(new HashSet<User>());
- room1.setAddress("NTU-M8-419");
- room1.addUser(user1);
- room1.addUser(user2);
-
- user1.setRoom(room1);
- user2.setRoom(room1);
-
- Transaction tx = session.beginTransaction();
- session.save(room1);
- tx.commit();
- session.close();
- sessionFactory.close();
- }
- }
此时生成的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了。