`
df274119386
  • 浏览: 55668 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Hibernate表关系之一对多(inverse详解)

阅读更多



在映射一对多表关系的时候存在一个inverse的问题,一直以来对inverse不怎么了解,今天用到它想要弄明白,在网上看了无数个帖子还是不懂,最后终于看到一位高人的一篇帖子,解释得很透彻,终于彻底了解inverse的含义了,下面说说一对多表关系的应用和inverse详解:
以父与子关系为例:父亲可以有多个孩子,而孩子只能有一个父亲。那么反映到数据表是这样实现的:
create table parent(
pid int auto_increment primary key,
pname varchar(20) not null
)
create table child(
cid int auto_increment primary key,
pid int not null,       //在孩子表中添加父亲表的外键,实现一对多
cname varchar(20) not null
)

用Hibernate自动生成的两个映射类,以Set集合方式表示一对多,以一个父亲对象方式表示多对一:
public class Child {
private Integer cid;
private Parent parent;     //属于哪个父亲
private String cname;
...
}
public class Parent {
private Integer pid;
private String pname;
private Set childs = new HashSet(0);     //包含孩子的集合
...
}

关键仍然是两个映射文件:
Child.hbm.xml:
<hibernate-mapping>
     <class name="com.pojo.Child" table="child" catalog="test">
         <id name="cid" type="java.lang.Integer">
             <column name="cid" />
             <generator class="native" />
         </id>
        //多对一的属性为parent,对应数据库中的字段为pid,级联更新为all
        <many-to-one name="parent" class="com.pojo.Parent" fetch="select" cascade="all">
             <column name="pid" />
         </many-to-one>
         <property name="cname" type="java.lang.String">
             <column name="cname" length="20" not-null="true" />
         </property>
     </class>
</hibernate-mapping>

Parent.hbm.xml:
<hibernate-mapping>
     <class name="com.pojo.Parent" table="parent" catalog="test">
         <id name="pid" type="java.lang.Integer">
             <column name="pid" />
             <generator class="native" />
         </id>
         <property name="pname" type="java.lang.String">
             <column name="pname" length="20" not-null="true" />
         </property>
       <set name="childs" inverse="true" cascade="all">   //描述孩子集合,把控制权交给孩子
             <key>
                 <column name="pid" not-null="true" />   //以Pid来分辨哪个孩子是属于这个父亲的
             </key>
             <one-to-many class="com.pojo.Child" />
         </set>
     </class>
</hibernate-mapping>

测试类:
Parent p=new Parent();
Child c1=new Child();
Child c2=new Child();
p.setPname("xpc5");
c1.setCname("cloud");
c1.setParent(p);     //设置孩子1的父亲为p
c2.setCname("cloud1");
c2.setParent(p);     //设置孩子2的父亲为p
p.getChilds().add(c1);     //为父亲添加孩子1
p.getChilds().add(c2);     //为父亲添加孩子2

session.save(p);

运行后在插入一个父亲记录的同时,两个孩子记录被自动插入

下面详细说明一下inverse的作用:
inverse是反转的意思,在Hibernate中inverse决定谁掌有控制权,即表之间的关系谁来维护,那么当inverse="true"表示交出控制权,inverse="false"表示不交出控制权,这样理解有些难度,网上大多对此块讲解不清楚,下面以我自己的理解说明,首先来看实例,还以上面为例,在Parent.hbm.xml中有这样的描述:
<set name="childs" inverse="true" cascade="all">
...
</set>
首先说明这个映射文件是描述Parent类的,那么set描述的是Child集合,inverse="true"意为交出控制权,整体意思就是Parent把控制权交给了Child,也就是说由Child来维护表关系。如果inverse="false"表示不交出控制权,那么当然由Parent自己来维护表关系了,值得提到的是在Child映射文件中没有提到由谁来控权,默认的是inverse="false",就是由自己控权,即Child,进一步说当Parent那边inverse="false"不交控权的时候,实际上是两个类都有责任来维护表关系。说到这里可能会问到底控权维护表关系是什么意思呢?下面来看测试类代码:
Parent p=new Parent();
Child c1=new Child();
p.setPname("xpc5");
c1.setCname("cloud");
c1.setParent(p);  
p.getChilds().add(c1);  
session.save(p);
这样写无论谁负责维护数据插入都没问题,那么我们改动一下试试,现在由Child负责维护,c1.setParent(p)是Child类与Parent类关联的关键,那么把句注释掉再试试,运行后执行语句是一样的,但是查看表记录你会发现Parent表能正确插入记录,而Child表中pid字段为空,这正是因为c1.setParent(p)这句是Child与Parent关联的关键而你又把它注释了,做为控权的Child没有设置与Parent关联,那么这两表之间的联系就消失了,即便有p.getChilds().add(c1)这句也无法实现关联,因为p不是控权。而当你修改Parent映射文件中的inverse="false"的时候,父亲和孩子都负责维护,那么什么都不动再试上面的程序,执行后的结果双方都可正确被插入,因为此时有p.getChilds().add(c1)这句存在就可以了,因为Parent也有控权。

那么为什么要使用inverse呢,让双方都有控权不好吗?下面来看,当Parent负责维护关系的时候,由于它包含一个孩子集合,它无法知道哪些孩子已经指向自己了,所以为了确保正确性,它要更新所有孩子的pid,让它指向自己,这样就引出了效率问题,若存在100个孩子,那么就无形中多做了100个update,所以显然,这个父子关系由孩子来维护比较省力.减轻了数据库的负担。



《inverse的作用:在hibernate中是通过inverse的设置来决定是有谁来维护表和表之间的关系的。
我们说inverse设立不当会导致性能低下,其实是说inverse设立不当,会产生多余重复的SQL语句甚至致使JDBC exception的throw。这是我们在建立实体类关系时必须需要关注的地方。一般来说,inverse=true是推荐使用,双向关联中双方都设置 inverse=false的话,必会导致双方都重复更新同一个关系。但是如果双方都设立inverse=true的话,双方都不维护关系的更新,这也是 不行的,好在一对多中的一端:many-to-one默认是inverse=false,避免了这种错误的产生。但是多对多就没有这个默认设置了,所以很 多人经常在多对多的两端都使用inverse=true,结果导致连接表的数据根本没有记录,就是因为他们双分都没有责任维护关系。所以说,双向关联中最 好的设置是一端为inverse=true,一端为inverse=false。一般inverse=false会放在多的一端,那么有人提问了, many-to-many两边都是多的,inverse到底放在哪儿?其实hibernate建立多对多关系也是将他们分离成两个一对多关系,中间连接一个连接表。所以通用存在一对多的关系,也可以这样说:一对多是多对多的基本组成部分。》


------感谢frankensteinlin网友的强帖!



本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/hnmoma/archive/2010/05/03/5553528.aspx
分享到:
评论

相关推荐

    JavaEE学习笔记之Hibernate表关系之一对多(inverse详解)

    本文将深入探讨Hibernate中的一对多关系,并重点解析`inverse`属性的作用及其应用。 一对多关系是数据库设计中常见的关联类型,例如一个用户可以拥有多个订单,一个班级可以包含多个学生等。在Hibernate中,通过...

    Hibernate中cascade与inverse属性详解

    Hibernate中cascade与inverse属性详解

    Hibernate对象关系详解

    在Hibernate的XML映射文件中,集合类型的关联关系经常使用`&lt;set&gt;`标签,如`&lt;set&gt;`下的`name`属性指定集合属性名,`table`属性指定中间表(多对多关系时),`inverse`属性表示维护关系的责任方,`cascade`属性控制...

    hibernate配置文件详解

    * `set`:定义一对多关联关系 这些配置项是 Hibernate 建立对象关系映射所需的基本信息。 Hibernate 配置文件是其核心组件之一,用于定义 Hibernate 的运行期参数。通过 hibernate.cfg.xml 和 .hbm.xml 文件,我们...

    hibernate集合映射inverse和cascade详解.txt

    在Hibernate中,`inverse`属性主要用于多对一或一对多的关系中,用于指定哪一方负责维护关系。当两个实体之间存在关联时,如果一方的集合变更,那么另一方的实体可能也需要更新。这时,`inverse`属性就变得尤为重要...

    hibernate inverse和cascade的详细讲解

    - **多对多**:例如,一个`Student`和多个`Course`课程的关系,`inverse`属性通常放在独立的关系表中,并且只能在一方设置为`true`,另一方为`false`,以确保关系的正确维护。 #### 三、Cascade 属性详解 `cascade...

    Hibernate一对多映射配置详解

    以下是对Hibernate一对多映射配置的详解: 一、XML文件配置 1. 单向关联 在这种配置中,关系只在一个方向上定义,例如User类有多个Account。在User的配置文件中,不直接声明与Account的关联,而是在Account的配置...

    Hibernate关联关系配置

    在Hibernate中,通常通过创建一个关联表来实现多对多关系。例如,一个学生可以选修多门课程,一门课程也可以被多名学生选修。 3. **联合主键**: 联合主键指的是多个字段共同作为表的主键。在Hibernate中,可以通过...

    hibernate中一对多配置

    **多对一关系详解:** 与一对多相反,多对一关系是多个子类实例指向一个父类实例。在上面的用户和订单例子中,如果我们将焦点放在订单上,每个订单都有一个关联的用户,这就是多对一关系。 1. **配置方式:** - ...

    hibernate表关联关系

    在Hibernate中,`many-to-many`关联关系是指两个实体间的一种多对多的关系。这种关系通常需要通过一个中间表来实现,该中间表用于存储两个实体之间的关联信息。下面我们将通过具体的例子来解释这一概念。 假设我们...

    Hibernate学习笔记和资料

    hibernate中一对一,一对多,多对多关系的配置,延迟加载,cascade,inverse hibernate查询方式概述,HQL查询,QBC查询,分页,结果集封装方式 ,高级查询 查询的优化,一级缓存,二级缓存,批量查询,注解方式

    hibernate对映射xml的一对多的双向关联详解

    在Java的持久化框架Hibernate中,对象关系映射(ORM)是其核心功能之一,它允许我们将数据库表与Java类进行映射,使得在数据库操作上可以使用面向对象的方式。本篇文章将深入探讨 Hibernate 中的一对多双向关联映射...

    hibernate一对多双向

    一对多(One-to-Many)关联是实体之间最常见的关系类型之一,表示一个实体可以与多个其他实体相关联,而后者只能与前者的一个实例相关联。例如,在一个公司组织结构中,一个部门可以有多个员工,但每个员工只能属于...

    hibernate关系映射网址

    本文将详细介绍Hibernate中的关系映射机制,包括一对一、一对多、多对一以及多对多等不同类型的映射方式,并探讨其背后的原理及最佳实践。 #### 二、Hibernate关系映射基础 ##### 2.1 映射文件简介 在Hibernate中...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part2

     7.1 建立多对一的单向关联关系  7.1.1 元素的not-null属性  7.1.2 级联保存和更新  7.2 映射一对多双向关联关系  7.2.1 元素的inverse属性  7.2.2 级联删除  7.2.3 父子关系  7.3 映射一对多双向自身关联...

    Hibernate 配置详解 (二)

    本文将更加深入地解析另一种重要的配置文件——`*.hbm.xml`,特别是如何通过此类文件来管理实体与数据库表之间的映射关系,以及处理复杂的关联关系,如一对一、一对多、多对一和多对多。 #### `*.hbm.xml`文件解析 ...

    Hibernate映射关联详解

    在关系型数据库设计中,一对多关联是常见的数据组织方式之一。而在面向对象编程语言中,这种关系则通常通过集合(如Set或List)来实现。本文将重点探讨如何在Hibernate框架下实现一对多双向关联。 #### 二、基本...

    12 Hibernate 一对多.doc

    本文将深入探讨Hibernate框架中的一对多关系映射,并以MyEclipse 6为开发环境,通过一个实战案例来展示如何配置和使用。在数据库设计中,一对多关系表示一个实体可以与多个其他实体相关联,例如一个家庭可以有多名...

Global site tag (gtag.js) - Google Analytics