`
lysongfei
  • 浏览: 60386 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

hibernate 关联映射总结

阅读更多


  Hibernate关系映射 收藏
     总结下实体与实体之间的多对一、一对多、一对一、多对多如何与Java对象之间进行映像,采用Oracle。

1、多对一

例如在学校寝室中,学生与寝室的关系就是多对一的关系,多个学生可以居住于一个寝室。

//创建一个表空间

create tablespace allenspace datafile 'c:\allenspace' size 15M autoExtend on next

10M permanent online;

//创建表user1

create table user1(id int primary key,name varchar2(20)default '' not null,roomid int)tablespace allenspace;

//创建表room

create table room(id int primary key,address varchar2(50)default '' not null)tablespace allenspace;

 

User.java和Room.java类

User类中有一room属性,将参考至Room实例,多个User实例可共同参考一个Room实例。

 

package cn.jjm.hibernate;

public class User {
    private int id;
    private String name;
    private Room room;
    
    public User(){
        
    }
    public int getId() {
        return id;
    }
    public void setId(int 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;
    }   
}

package cn.jjm.hibernate;

public class Room {
    private int id;
    private String address;
    
    public Room(){
        
    }
    
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
}
映射文件。。。。

Room.hbm.xml

<hibernate-mapping>
    <class name="cn.jjm.hibernate.Room" table="ROOM" schema="SYS">
        <id name="id" type="java.lang.Integer">
            <column name="ID" precision="22" scale="0" />
            <generator class="assigned" />
        </id>
        <property name="address" type="java.lang.String">
            <column name="ADDRESS" length="50" not-null="true" />
        </property>
        
    </class>
</hibernate-mapping>
User.hbm.xml

<hibernate-mapping>
    <class name="cn.jjm.hibernate.User" table="USER1" schema="SYS">
        <id name="id" type="java.lang.Integer">
            <column name="ID" precision="22" scale="0" />
            <generator class="assigned" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" length="20" not-null="true" />
        </property>
        
        <many-to-one name="room" 
                     column="ROOMID" 
                     class="cn.jjm.hibernate.Room"
                     cascade="all"
                     outer-join="true"/>         
    </class>
</hibernate-mapping>
在<many-to-one>的设定中,cascade表示主控方(User)进行save-update、delete等相关操作时,被控方(Room)是否也一并进行相关操作,简单的说,也就是您储存或更新User实例时,当中的Room实例是否一并对数据库发生储存或操作,设定为 all,表示主控方任何操作,被控方也进行对应操作。

存储测试:

 

   Room room1 = new Room(); 
   room1.setId(1001);
   room1.setAddress("NTU-M8-419"); 
   Room room2 = new Room(); 
   room2.setId(1002);
   room2.setAddress("NTU-G3-302"); 

   User user1 = new User();
   user1.setId(101);
   user1.setName("allen"); 
   user1.setRoom(room1); 

   User user2 = new User();
   user2.setId(102);
   user2.setName("candy"); 
   user2.setRoom(room1); 

   User user3 = new User();
   user3.setId(103);
   user3.setName("momor"); 
   user3.setRoom(room2);

   session.save(user1);
   session.save(user2);
   session.save(user3);

2、一对多

在多对一中,User对Room是多对一的关系,User实例维护着对Room实例的参考,如果将这个关系反过来,由Room实例维护对多个User实例的数据,就是一对多的关系。

 

User.java和Room.java类

package cn.jjm.hibernate;

public class User {
    private int id;
    private String name;
    
    public User(){
        
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}


package cn.jjm.hibernate;

import java.util.Set;
public class Room {
    private int id;
    private String address;
    private Set users;
    
    public Room(){
        
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Set getUsers() {
        return users;
    }

    public void setUsers(Set users) {
        this.users = users;
    }
    //添加User对象
    public void addUser(User user){
        users.add(user);
    }
    //删除User对象
    public void removeUser(User user){
        users.remove(user);
    }
}

这种方式即所谓单向一对多关系,也就是Room实例知道User实例的存在,而User实例则没有意识到Room实例。
(在多对一中,则是单向多对一关系,即User知道Room的存在,但Room不知道User的存在。)

 

映射文件。。。

User.hbm.xml

<hibernate-mapping>
    <class name="cn.jjm.hibernate.User" table="USER1" schema="SYS">
        <id name="id" type="java.lang.Integer">
            <column name="ID" precision="22" scale="0" />
            <generator class="assigned" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" length="20" not-null="true" />
        </property>
    </class>
</hibernate-mapping>
Room.hbm.xml

<hibernate-mapping>
    <class name="cn.jjm.hibernate.Room" table="ROOM" schema="SYS">
        <id name="id" type="java.lang.Integer">
            <column name="ID" precision="22" scale="0" />
            <generator class="assigned" />
        </id>
        <property name="address" type="java.lang.String">
            <column name="ADDRESS" length="50" not-null="true" />
        </property>
        
        <set name="users" table="user1" cascade="all">
            <key column="ROOMID"/>
            <one-to-many class="cn.jjm.hibernate.User"/>
        </set>      
    </class>
</hibernate-mapping>

存储测试。。。

User user1 = new User();
user1.setId(104);
user1.setName("张无忌"); 

User user2 = new User();
user2.setId(105);
user2.setName("周芷若"); 

User user3 = new User(); 
user3.setId(106);
user3.setName("张三丰"); 

Room room1 = new Room(); 
room1.setId(1003);
room1.setUsers(new HashSet());
room1.setAddress("NTU-M8-345");
room1.addUser(user1);
room1.addUser(user2);

Room room2 = new Room();
room2.setId(1004);
room2.setUsers(new HashSet());
room2.setAddress("NTU-G3-322");
room2.addUser(user3);

session.save(room1);
session.save(room2)
3、双向关联(inverse)

在多对一、一对多中都是单向关联,也就是其中一方关联到另一方,而另一方不知道自己被关联。

如果让双方都意识到另一方的存在,这就形成了双向关联。

User.java和Room.java类

package cn.jjm.hibernate;

public class User {
    private int id;
    private String name;
    private Room room;
    
    public User(){
        
    }
    public int getId() {
        return id;
    }
    public void setId(int 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;
    }   
}


package cn.jjm.hibernate;

import java.util.Set;

public class Room {
    private int id;
    private String address;
    private Set users;
    
    public Room(){
        
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Set getUsers() {
        return users;
    }

    public void setUsers(Set users) {
        this.users = users;
    }
    //添加User对象
    public void addUser(User user){
        users.add(user);
    }
    //删除User对象
    public void removeUser(User user){
        users.remove(user);
    }
}

如此,User实例可参考至Room实例而维持多对一关系,而Room实例记得User实例而维持一对多关系。

映射文件。。。

User.hbm.xml

<hibernate-mapping>
    <class name="cn.jjm.hibernate.User" table="USER1" schema="SYS">
        <id name="id" type="java.lang.Integer">
            <column name="ID" precision="22" scale="0" />
            <generator class="assigned" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" length="20" not-null="true" />
        </property>  
        <many-to-one name="room" 
                     column="ROOMID" 
                     class="cn.jjm.hibernate.Room"
                     cascade="save-update"
                     outer-join="true"/>         
    </class>
</hibernate-mapping>
Room.hbm.xml

<hibernate-mapping>
    <class name="cn.jjm.hibernate.Room" table="ROOM" schema="SYS">
        <id name="id" type="java.lang.Integer">
            <column name="ID" precision="22" scale="0" />
            <generator class="assigned" />
        </id>
        <property name="address" type="java.lang.String">
            <column name="ADDRESS" length="50" not-null="true" />
        </property>
        <set name="users" table="user1" cascade="save-update">
            <key column="ROOMID"/>
            <one-to-many class="cn.jjm.hibernate.User"/>
        </set>      
    </class>
</hibernate-mapping>
映像文件双方都设定了cascade为save-update,所以您可以用多对一的方式来维持关联:

User user1 = new User();
user1.setId(104);
user1.setName("张无忌"); 

User user2 = new User();
user2.setId(105);
user2.setName("周芷若"); 

Room room1 = new Room(); 
room1.setId(1003);
room1.setAddress("NTU-M8-345");

user1.setRoom(room1);
user2.setRoom(room1);

session.save(user1);
session.save(user2);
或者反过来由一对多的方式来维持关联:

User user1 = new User();
user1.setId(104);
user1.setName("张无忌"); 

User user2 = new User();
user2.setId(105);
user2.setName("周芷若"); 

Room room1 = new Room(); 
room1.setId(1003);
room1.setUsers(new HashSet());
room1.setAddress("NTU-M8-345");

room1.addUser(user1);
room1.addUser(user2);

session.save(room1);

在一对多、多对一形成双向关联的情况下,可以将关联维持的控制权交给多的一方,这样会比较有效率,理由不难理解,就像是领导记住下属员工的姓名快,还是所有员工记住部门领导的姓名快。

 

以在一对多、多对一形成双向关联的情况下,可以在「一」的一方设定控制权反转,也就是当储存「一」的一方时,将关联维持的控制权交给「多」的一方。来看Room.hbm.xml

 


<hibernate-mapping>
    <class name="cn.jjm.hibernate.Room" table="ROOM" schema="SYS">
        <id name="id" type="java.lang.Integer">
            <column name="ID" precision="22" scale="0" />
            <generator class="assigned" />
        </id>
        <property name="address" type="java.lang.String">
            <column name="ADDRESS" length="50" not-null="true" />
        </property>
        <set name="users" table="user1" cascade="save-update" inverse="true">
            <key column="ROOMID"/>
            <one-to-many class="cn.jjm.hibernate.User"/>
        </set>      
    </class>
</hibernate-mapping>
由于关联的控制权交给「多」的一方了,所以直接储存「一」方前,「多」的一方必须意识到「一」的存在,所以..


User user1 = new User();
user1.setId(104);
user1.setName("张无忌"); 

User user2 = new User();
user2.setId(105);
user2.setName("周芷若"); 

Room room1 = new Room(); 
room1.setId(1003);
room1.setAddress("NTU-M8-345");

user1.setRoom(room1);
user2.setRoom(room1);

session.save(room1);

4、一对一 唯一外键关联

每一个User配给一间Room,形成一对一。看类。。。

package cn.jjm.hibernate;

public class User {
    private int id;
    private String name;
    private Room room;
    
    public User(){
        
    }
    public int getId() {
        return id;
    }
    public void setId(int 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;
    }   
}


package cn.jjm.hibernate;

import java.util.Set;

public class Room {
    private int id;
    private String address;
    private Set users;
    
    public Room(){
        
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Set getUsers() {
        return users;
    }

    public void setUsers(Set users) {
        this.users = users;
    }
    //添加User对象 
    public void addUser(User user){
        users.add(user);
    }
    //删除User对象 
    public void removeUser(User user){
        users.remove(user);
    }
}

用外键来完成一对一,其实就是限制多对一关系中,「多」的一方只能有一个参考至「一」的一方,也就是多对一关系的一个特例,这可以在映像文件中使用<many-to-one>标签时,加上"unique"属性来设定。

User.hbm.xml

<hibernate-mapping>
    <class name="cn.jjm.hibernate.User" table="USER1" schema="SYS">
        <id name="id" type="java.lang.Integer">
            <column name="ID" precision="22" scale="0" />
            <generator class="assigned" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" length="20" not-null="true" />
        </property>
        
        <many-to-one name="room" 
                     column="ROOMID" 
                     class="cn.jjm.hibernate.Room"
                     cascade="all"
                     outer-join="true"
                     unique="true"/>         
    </class>
</hibernate-mapping>
如果要再完成双向一对一的关系,则可以在Room.hbm.xml中使用<one-to-one>标签来定义...

<hibernate-mapping>
    <class name="cn.jjm.hibernate.Room" table="ROOM" schema="SYS">
        <id name="id" type="java.lang.Integer">
            <column name="ID" precision="22" scale="0" />
            <generator class="assigned" />
        </id>
        <property name="address" type="java.lang.String">
            <column name="ADDRESS" length="50" not-null="true" />
        </property>
        <one-to-one name="user"
                    class="cn.jjm.hibernate.User"
                    property-ref="room"/>
    </class>
</hibernate-mapping>

在<one-to-one>中,property-ref告诉Hibernate,查询出user并将其参考至room。

存储测试...

User user1 = new User();
user1.setId(104);
user1.setName("张无忌"); 
Room room1 = new Room(); 
room1.setId(1003);
room1.setAddress("NTU-M8-345");
user1.setRoom(room1);

User user2 = new User();
user2.setId(105);
user2.setName("周芷若"); 
Room room2 = new Room();
room2.setId(1004);
room2.setAddress("NTU-G3-322");
user2.setRoom(room2);

session.save(user1);
session.save(user2);
5、一对一 主键关联

一对一关联的另一种方式,是限制两个实体的主键必须一致,如此直接透过两个表格的主键就可确定一对一关联,而不用额外的外键参考。

User类别与Room类别的设计使用一对一(唯一外键关联)中的设计即可。

User.hbm.xml

<hibernate-mapping>
    <class name="cn.jjm.hibernate.User" table="USER1" schema="SYS">
        <id name="id" type="java.lang.Integer">
            <column name="ID" precision="22" scale="0" />
            <generator class="assigned" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" length="20" not-null="true" />
        </property>
        
        <one-to-one name="room" 
                     column="ROOMID" 
                     class="cn.jjm.hibernate.Room"
                     cascade="all"/>         
    </class>
</hibernate-mapping>

Room.hbm.xml

<hibernate-mapping>
    <class name="cn.jjm.hibernate.Room" table="ROOM" schema="SYS">
        <id name="id" type="java.lang.Integer">
            <generator class="foreign"> 
                <param name="property">user</param>
            </generator>
        </id>
        <property name="address" type="java.lang.String">
            <column name="ADDRESS" length="50" not-null="true" />
        </property>
        <one-to-one name="user"
                    class="cn.jjm.hibernate.User"
                    constrained="true"/>
    </class>
</hibernate-mapping>
在Room的id主键上,使用foreign表示与外键共享主键,也就是与User实体共享主键,而constrained设定为true,表示约束room的主键必须与user中对应数据的主键相同。]

存储测试。。。

User user1 = new User();
user1.setId(104);
user1.setName("张无忌"); 
Room room1 = new Room(); 
room1.setId(1003);
room1.setAddress("NTU-M8-345");
user1.setRoom(room1);
room1.setUser(user1);

User user2 = new User();
user2.setId(105);
user2.setName("周芷若"); 
Room room2 = new Room();
room2.setId(1004);
room2.setAddress("NTU-G3-322");
user2.setRoom(room2);
room2.setUser(user2);

session.save(user1);
session.save(user2);
6、多对多关联

在数据库表格上要进行多对多对应,可以藉由一个中介表格来完成,也就是藉由多对一、一对多来完成多对多关联。


多对多由于使用了中介表格,在查询效率不彰,且在程序的对象模式上,多对多会使得对象与对象之间彼此依赖,并不是一个很好的设计方式,在设计上应避免使用多对多关系。

这里就不做多对多了。。。

附录:

1、<many-to-one/>的cascade属性
没有session.save(对象),即只执行保存多的方面,不执行保存一的方面对象。
如果没有cascade属性,则这样会抛异常。
有session.save(room1),两方面对象都保存。没有cascade属性也可。


2、<set/>的inverse属性
执行session.save(对象)的时候
默认为false
Hibernate: select user_.ID, user_.NAME as NAME1_ from USER1 user_ where user_.ID=?
Hibernate: select user_.ID, user_.NAME as NAME1_ from USER1 user_ where user_.ID=?
Hibernate: select user_.ID, user_.NAME as NAME1_ from USER1 user_ where user_.ID=?
Hibernate: insert into ROOM (ADDRESS, ID) values (?, ?)
Hibernate: insert into USER1 (NAME, ID) values (?, ?)
Hibernate: insert into USER1 (NAME, ID) values (?, ?)
Hibernate: insert into USER1 (NAME, ID) values (?, ?)
Hibernate: update USER1 set ROOMID=? where ID=?
Hibernate: update USER1 set ROOMID=? where ID=?
Hibernate: update USER1 set ROOMID=? where ID=?

设置为true
Hibernate: select user_.ID, user_.NAME as NAME1_ from USER1 user_ where user_.ID=?
Hibernate: select user_.ID, user_.NAME as NAME1_ from USER1 user_ where user_.ID=?
Hibernate: select user_.ID, user_.NAME as NAME1_ from USER1 user_ where user_.ID=?
Hibernate: insert into ROOM (ADDRESS, ID) values (?, ?)
Hibernate: insert into USER1 (NAME, ID) values (?, ?)
Hibernate: insert into USER1 (NAME, ID) values (?, ?)
Hibernate: insert into USER1 (NAME, ID) values (?, ?)

3、<set/>的cascade属性
若解除user对象与room的关系,希望Hibernate自动删除,避免不必要的SQL更新操作。
设置cascade为all-delete-orphan。

 

分享到:
评论
1 楼 梅花灿 2011-07-24  
好东西啊  、收了

相关推荐

    Hibernate关联映射总结

    ### Hibernate关联映射总结 #### 一、基础知识 在探讨Hibernate中的关联映射之前,我们需要先理解几个基本概念,这将有助于我们更好地理解和应用这些关联映射。 - **主键**(Primary Key):主键是用来唯一标识一...

    hibernate关联映射详解

    hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,包含4个说明文档,分别详细解说了hibernate关联映射的...

    hibernate映射关系总结

    hibernate开发的关系: one-to-one,many-to-one,many-to-many学习经验总结

    hibernate关联映射实例

    本文将深入探讨“hibernate关联映射实例”中的关键知识点,包括一对多、多对多和继承映射,这些都是Hibernate中至关重要的概念。 1. **一对多关联映射**: 在现实世界中,一个实体可能会与多个其他实体相关联,...

    hibernate关联映射的作用和常用属性解释

    ### Hibernate关联映射的作用与常用属性详解 #### 关联映射概述 在对象关系映射(Object Relational Mapping,简称ORM)技术中,Hibernate作为Java领域内非常成熟且功能强大的框架之一,它允许开发者将Java类映射...

    Hibernate关联映射

    在 Hibernate 映射中,需要使用 `one-to-one` 元素,并设置 `constrained="true"`,表明该类的主键由关联类生成。 3. Hibernate 一对一连接表单向关联: 这种关联方式是通过额外的连接表来实现一对一关系的。连接...

    hibernate多对多关联映射

    在Java的持久化框架Hibernate中,多对多关联映射是一种常见的关系数据库模型映射方式,用于处理两个实体之间存在多个实例互相关联的情况。本文将深入探讨Hibernate如何实现多对多关联映射,并通过实际例子解析相关...

    Hibernate关联映射.rar

    本教程“Hibernate关联映射.rar”聚焦于Hibernate中的关联映射,特别是多对一和一对多的关系映射,非常适合初学者了解和实践。 首先,我们要理解什么是关联映射。在数据库中,表与表之间存在各种关系,如一对一、一...

    Hibernate集合映射与关联关系

    本主题将深入探讨Hibernate集合映射与关联关系,包括"student与Score的Map集合关系"、"student与class的多对一"以及"一对多映射"的概念。 首先,让我们理解一下Hibernate中的集合映射。在关系型数据库中,一个实体...

    Hibernate一对一主键关联映射(双向关联)

    在Java的持久化框架Hibernate中,一对一(One-to-One)关联映射是一种常见的关系数据库模型映射方式。这种关联通常发生在两个实体之间,且每个实体都只有一个对应的实例。本篇文章将详细探讨双向一对一主键关联映射...

    hibernate 全面学习->hibernate 关联映射学习

    总的来说,这个压缩包提供了丰富的Hibernate关联映射的学习资源,涵盖了从基础到进阶的各种关联类型。通过学习这些示例,你将能够熟练掌握如何在Java项目中使用Hibernate进行数据持久化,并灵活地处理各种数据库关系...

    hibernate关联映射详解SSH 多对多,一对多关系对象映射

    在Java的持久化框架Hibernate中,关联映射是至关重要的概念,它允许我们将数据库中的表关系映射到对象之间的关系。SSH(Struts、Spring、Hibernate)是经典的Java Web开发框架,其中Hibernate负责数据访问层,提供了...

    Hibernate关联映射-one to one单向外键关联

    本话题主要探讨的是Hibernate中的一种关联映射方式——一对一(One-to-One)单向外键关联。这种关联模式通常用于两个实体之间存在唯一对应的关系,例如一个用户对应一个唯一的账户。 在Hibernate中,一对一关联可以...

    hibernate关联关系总结

    Hibernate关联关系是Java持久化框架Hibernate中的核心概念,它允许我们在数据库中建立对象之间的关系映射,以便在程序中操作对象时,可以自动处理与数据库的交互。本篇将深入探讨Hibernate的四种主要关联关系:一对...

    Hibernate 关联映射

    这可能是测试Hibernate关联映射的一个示例项目或者类。通常,这样的测试会包含各种关联映射的实例,如实体类的定义,配置文件或注解,以及测试用例,用于验证关联映射是否按预期工作。 **详细知识讲解:** 1. **一...

    hibernate 关联映射(一) many to one

    本文将深入探讨“Hibernate关联映射中的Many-to-One关系”。 Many-to-One关联是现实世界中常见的关系类型,比如一个学生可以对应多个课程,而一个课程可能被多个学生选修。在数据库中,这通常表现为一对多(One-to-...

    hibernate 关联映射(二) one to one(单向)

    总结来说,Hibernate的One-to-One关联映射提供了一种方便的方式来处理一对一关系,通过源码分析我们可以更深入地理解其内部机制。在实际开发中,根据业务需求合理配置`@OneToOne`注解,可以提高代码的可读性和数据库...

    Hibernate 关联关系映射分类

    在深入探讨Hibernate关联关系映射分类之前,我们首先简要回顾一下Hibernate框架的基本概念。Hibernate是一种持久层框架,主要用于Java应用程序中的对象关系映射(ORM),它能够将面向对象的数据模型转换为数据库中的...

Global site tag (gtag.js) - Google Analytics