hibernate3学习笔记(十八)|关系映射:一对多

接上例: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了。

生命不息,奋斗不止,就像我们常说的一句话;

hibernate3学习笔记(十八)|关系映射:一对多

相关文章:

你感兴趣的文章:

标签云: