Hibernate入门22 - 一对一实体映像

来源:互联网 发布:阿里御膳房数据体系 编辑:程序博客网 时间:2024/06/07 03:52

入门 22 - 一对一实体映像

 假设我们之前范例的User与Room是一对一的关系,也就是每一个人分配一个房间,先看看这两个类别:

User.java

package onlyfun.caterpillar;

 

public class User {

    private long id;

    private String name;

    private Room room;

  

    public long getId() {

        return id;

    }

    public void setId(long id) {

        this.id = id;

    }

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public Room getRoom() {

        return room;

    }

    

    public void setRoom(Room room) {

        this.room = room;

    }    

}

 

Room.java

package onlyfun.caterpillar;

 

public class Room {

   private long id;

   private String address;

   private User user;

  

   public long getId() {

       return id;

   }

   public void setId(long id) {

       this.id = id;

   }  

   public String getAddress() {

       return address;

   }

   public void setAddress(String address) {

       this.address = address;

   }

   public User getUser() {

         return user;

   }

   public void setUser(User user) {

       this.user = user;

   }

}


 要映像User与Room的一对一关系,我们可以有两种方式,一种是透过外键参考,在之前的多对一的例子中即使外键参考的例子,我们现在限制多对一为一 对一,只要在User.hbm.xml中的<many-to-one>上加上unique="true",表示限制一个User有一独有的 Room:

User.hbm.xml

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping

    PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"

    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

 

<hibernate-mapping>

 

    <class name="onlyfun.caterpillar.User" table="USER">

 

        <id name="id" column="USER_ID" unsaved-value="0">

            <generator class="increment"/>

        </id>

 

        <property name="name">

            <column name="NAME" length="16" not-null="true"/>

        </property>

    

        <many-to-one name="room"

                     column="ROOM_ID"

                     class="onlyfun.caterpillar.Room"

                     cascade="all"

                     unique="true"/>        

    </class>

 

</hibernate-mapping>


 这就完成了单向的一对一映射,我们可以在Room.hbm.xml上加入参考回User的设定,使其成为双向的一对一映射,如下:

Room.hbm.xml

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping

    PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"

    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

 

<hibernate-mapping>

 

    <class name="onlyfun.caterpillar.Room" table="ROOM">

 

        <id name="id" column="ROOM_ID" unsaved-value="0">

            <generator class="increment"/>

        </id>

 

        <property name="address" type="string"/>

      

        <one-to-one name="user"

                    class="onlyfun.caterpillar.User"

                    property-ref="room"/>

    </class>

 

</hibernate-mapping>


 在<one-to-one>的设定中,我们告诉Hibernate,Room返向参考回User的room属性。
 使用以下的程序来测试数据的储存:

HibernateTest.java

import onlyfun.caterpillar.*;

import net.sf.hibernate.*;

import net.sf.hibernate.cfg.*;

 

public class HibernateTest {

    public static void main(String[] args) throws HibernateException {

        SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();

      

        Room room = new Room();

        room.setAddress("NTU-M8-419");      

      

        User user1 = new User();

        user1.setName("bush");      

      

        user1.setRoom(room);

        room.setUser(user1);

      

        Session session = sessionFactory.openSession();

        Transaction tx= session.beginTransaction();

        session.save(user1);

 

        tx.commit();

        session.close();

 

        sessionFactory.close();

    }

}


 数据表的实际例子,与多对一映像时相同,只不过现在一个User只能对应一个Room。
 另一个映像一对一的方式是使用主键关联,限制两个数据表的主键使用相同的值,如此一个User与Room就是一对一关系,在User.hbm.xml这边,只要使用<one-to-one>设定关联即可:

User.hbm.xml

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping

    PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"

    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

 

<hibernate-mapping>

 

    <class name="onlyfun.caterpillar.User" table="USER">

 

        <id name="id" column="USER_ID" unsaved-value="0">

            <generator class="increment"/>

        </id>

 

        <property name="name">

            <column name="NAME" length="16" not-null="true"/>

        </property>

    

        <one-to-one name="room"

                    class="onlyfun.caterpillar.Room"

                    cascade="all"/>      

    </class>


 在Room.hbm.xml这边,必须限制其主键与User的主键相同,而在属性上,使用constrained="true"告诉Hibernate参考至User的主键:

Room.hbm.xml

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping

    PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"

    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

 

<hibernate-mapping>

 

    <class name="onlyfun.caterpillar.Room" table="ROOM">

 

        <id name="id" column="ROOM_ID" unsaved-value="0">

            <generator class="foreign">

                <param name="property">user</param>

            </generator>

        </id>

 

        <property name="address" type="string"/>

      

        <one-to-one name="user"

                    class="onlyfun.caterpillar.User"

                    constrained="true"/>

    </class>

 

</hibernate-mapping>


 只要改变映像文件即可,程序的部份无需修改,数据库中的实际储存例子如下:

mysql> select * from USER;

+---------+-------------+

| USER_ID | NAME        |

+---------+-------------+

|       1 | bush        |

|       2 | caterpillar |

+---------+-------------+

2 rows in set (0.00 sec)

 

mysql> select * from ROOM;

+---------+------------+

| ROOM_ID | address    |

+---------+------------+

|       1 | NTU-M8-419 |

|       2 | NTU-M8-420 |

+---------+------------+

2 rows in set (0.00 sec)