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

Hibernate中的Inverse

阅读更多
以前写HBM,用一对多或多对多的时候默认总是加上“inverse=true”。当时想法很简单就是由双方来维护之间的关联关系。今天才终于明白inverse的真正含义了!




(1)其实inverse不复杂,但是要真正明白还是要稍微看一下源码。inverse的真正作用就是指定由哪一方来维护之间的关联关系。当一方中指定了“inverse=false”(默认),那么那一方就有责任负责之间的关联关系,说白了就是hibernate如何生成Sql来维护关联的记录!举个最简单的一对多父子关系。那么代码就写成:

父亲中的关系映射
{set name="children" lazy="true" inverse="true"}
      {key column="parent_id"/}
      {one-to-many class="test.Child"/}
{/set}

儿子中关系映射
{many-to-one name="parent" column="parent_id" not-null="true"/}


Parent p = new Parent();
Child c = new Child();
c.setParent(p);  //维护父子之间关系
p.getChildren().add(c);

session.save(p);
session.flush();

注意:{many-to-one}总是设成“inverse=false”的,而且这个属性在Mapping中是不存在的!

这样运行的下来的结果就是:

Hibernate: insert into parent (id) values (?)
Hibernate: insert into child (parent_id, id) values (?, ?)

那么假如c.setParent(p)注释掉,结果就是:

Hibernate: insert into parent (id) values (?)

比较结果显而易见!此外,inverse还有一个重要特点就是会优化Sql。(具体可以把SHOW_SQL这个属性打开,然后观察一下就知道了)







(2)接下来再看看update,还是父子的例子:

Parent p = (Parent) session.load(Parent.class, parentId);
Parent p2 = (Parent) session.load(Parent.class, parentId2);
       
c = (Child) session.find(
            "from Child as child where child.parent = ?",
            p, Hibernate.entity(Parent.class)).get(0);

// 改变儿子c的关系
p.getChildren().remove(c);
p2.getChildren().add(c);
c.setParent(p2);

这样运行下来的结果就是:

Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=? //get parent 1
Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=? //get parent 2
Hibernate: select child0_.id as id, child0_.parent_id as parent_id from child child0_ where (child0_.parent_id=? )

Hibernate: select child0_.id as id__, child0_.id as id, child0_.parent_id as parent_id from child child0_ where child0_.parent_id=?
Hibernate: select child0_.id as id__, child0_.id as id, child0_.parent_id as parent_id from child child0_ where child0_.parent_id=?

Hibernate: update child set parent_id=? where id=?(正确更新了)

那么根据上面的结论,关系应该是由“inverse=false”方来维护的,那么我把代码改成:

Parent p = (Parent) session.load(Parent.class, parentId);
Parent p2 = (Parent) session.load(Parent.class, parentId2);
       
c = (Child) session.find(
            "from Child as child where child.parent = ?",
            p, Hibernate.entity(Parent.class)).get(0);

//p.getChildren().remove(c);
//p2.getChildren().add(c);
c.setParent(p2);

这样运行下来的结果:

Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=? //get parent 1
Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=? //get parent 2
Hibernate: select child0_.id as id, child0_.parent_id as parent_id from child child0_ where (child0_.parent_id=? )

Hibernate: update child set parent_id=? where id=?

比较结果很明显,少了父加载儿子的过程,乍看下是成功更新了。实际上,结果和DB是不一致的。(原因很简单就是父亲p的children并没有被更新)

那么反过来改一下:

Parent p = (Parent) session.load(Parent.class, parentId);
Parent p2 = (Parent) session.load(Parent.class, parentId2);
       
c = (Child) session.find(
            "from Child as child where child.parent = ?",
            p, Hibernate.entity(Parent.class)).get(0);

p.getChildren().remove(c);
p2.getChildren().add(c);
//c.setParent(p2);

这样结果就成了:

Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=? //get parent 1
Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=? //get parent 2
Hibernate: select child0_.id as id, child0_.parent_id as parent_id from child child0_ where (child0_.parent_id=? ) //get children

Hibernate: select child0_.id as id__, child0_.id as id, child0_.parent_id as parent_id from child child0_ where child0_.parent_id=?
Hibernate: select child0_.id as id__, child0_.id as id, child0_.parent_id as parent_id from child child0_ where child0_.parent_id=?

显而易见,关联更新没有被执行(更新是由“inverse=false”方负责的,而这里恰恰被注释了)。












(3)


大多数情况下,很少使用“inverse=false”,但是我还是想仔细研究一下(这样可以更加理解“inverse=true”)。 ^_^
为什么很少使用“inverse=false”?原因很简单之前也提到过,就是不会对双向关系进行优化。

还是来看一个父子的例子:

父亲中的关系映射
{set name=children lazy=true inverse=false}
      {key column=parent_id/}
      {one-to-many class=test.Child/}
{/set}

儿子中关系映射
{many-to-one name=parent column=parent_id not-null=true/}

代码:

Parent p = new Parent();
Child c = new Child();
p.getChildren().add(c);
c.setParent(p);
session.save(p);
session.save(c);
session.flush();

结果:

Hibernate: insert into parent (id) values (?)
Hibernate: insert into child (parent_id, id) values (?, ?)
Hibernate: update child set parent_id=? where id=?

看到这里就应该明白我之前为什么说“inverse=true”会优化Sql了吧!还有之前也说过是由“inverse=false”来维护关系了,那这里就是由父亲来维护了。假设我在save(p)和save(c)之间掉flush(),结果又会是如何?事实上,是不可以这么做的!因为父亲负责维护关系,如果我在之间加入了flush(),那么就是无法关联更新了(父亲需要一个已经持久化的儿子来触发关联更新)

(4)

接下来再来看看update:

Parent p = (Parent) session.load(Parent.class, parentId);
Parent p2 = (Parent) session.load(Parent.class, parentId2);
       
c = (Child) session.find(
            "from Child as child where child.parent = ?",
            p, Hibernate.entity(Parent.class)).get(0);
p.getChildren().remove(c);
p2.getChildren().add(c);
c.setParent(p2);

结果:

Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=?    //get parent 1
Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=?    //get parent 2
Hibernate: select child0_.id as id, child0_.parent_id as parent_id from child child0_ where (child0_.parent_id=? )
//get first child for parent 1

Hibernate: select child0_.id as id__, child0_.id as id, child0_.parent_id as parent_id from child child0_ where child0_.parent_id=?
Hibernate: select child0_.id as id__, child0_.id as id, child0_.parent_id as parent_id from child child0_ where child0_.parent_id=?

Hibernate: update child set parent_id=? where id=?               // child.setParent
Hibernate: update child set parent_id=null where parent_id=?     //remove
Hibernate: update child set parent_id=? where id=?               // add

结果说明当设成“inverse=false”时,关系是由父亲和儿子来维护的。这种效率和之前我说的“inverse=true”低很多。

那么关系是由父亲来维护的,我又把代码改了一下:

Parent p = (Parent) session.load(Parent.class, parentId);
Parent p2 = (Parent) session.load(Parent.class, parentId2);
       
c = (Child) session.find(
            "from Child as child where child.parent = ?",
            p, Hibernate.entity(Parent.class)).get(0);
p2.getChildren().add(c);

结果:

Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=?    //get parent 1
Hibernate: select parent0_.id as id from parent parent0_ where parent0_.id=?    //get parent 2
Hibernate: select child0_.id as id, child0_.parent_id as parent_id from child child0_ where (child0_.parent_id=? )
//get first child for parent 1

Hibernate: select child0_.id as id__, child0_.id as id, child0_.parent_id as parent_id from child child0_ where child0_.parent_id=?
Hibernate: select child0_.id as id__, child0_.id as id, child0_.parent_id as parent_id from child child0_ where child0_.parent_id=?

Hibernate: update child set parent_id=? where id=?               // add

乍看之下对的,但是父亲p和p2的children的状态是不一致的!
分享到:
评论

相关推荐

    Hibernate中Inverse和Cascade的区别.html

    Hibernate中Inverse和Cascade的区别.html

    彻底明白Hibernate中的Inverse

    在Hibernate中,`Inverse`是一个重要的概念,它涉及到实体之间的关联管理。本文将深入探讨`Inverse`属性,以及它在Hibernate中的作用和应用场景。 一、Hibernate与对象关系映射 Hibernate通过ORM机制将Java对象与...

    Hibernate中cascade与inverse属性详解

    Hibernate中cascade与inverse属性详解

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

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

    hibernate inverse 个人总结.doc

    在探讨Hibernate的`inverse`属性之前,我们先要理解Hibernate中的对象关系映射(ORM)以及持久化机制。Hibernate是一个流行的Java ORM框架,它允许开发者将数据库操作转换为面向对象的编程模型,使得数据操作更加...

    hibernate inverse和cascade的详细讲解

    ### Hibernate Inverse 和 Cascade 的详细讲解 #### 一、引言 在ORM(Object-Relational Mapping)领域,Hibernate作为一款流行的Java持久层框架,它提供了丰富的API和配置选项来帮助开发者实现对象与数据库表之间...

    Hibernate中cascade和inverse应用

    在 Hibernate 框架中,`cascade` 和 `inverse` 是两个重要的概念,它们主要用于管理对象之间的持久化关系,特别是涉及到一对一(one-to-one)、一对多(one-to-many)和多对多(many-to-many)关系时。这两个属性都...

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

    在深入探讨Hibernate集合映射中的`inverse`与`cascade`属性之前,我们首先需要理解Hibernate框架的基本概念。Hibernate是一个开放源代码的对象关系映射(ORM)框架,它为Java应用程序提供了一种将对象模型与数据库...

    hibernate 级联(cascade和inverse)一对多

    在Java的持久化框架Hibernate中,级联操作(Cascade)和反转(Inverse)是两个重要的概念,它们主要用于管理对象关系模型中的关联关系。在一对多的关系中,这些特性可以帮助简化数据操作,提高代码的可读性和维护性...

    Hibernate_级联关系说明_-_关于cascade和inverse的用法

    在探讨Hibernate框架中的级联操作(cascade)与控制权反转(inverse)之前,我们需要先对Hibernate有一个基本的理解。Hibernate是一个开放源代码的对象关系映射(ORM)框架,它为Java应用提供了一种将对象模型映射到...

    Java框架面试题总结

    ### Java框架面试题总结 #### Struts篇 **1.... ... 谈谈Hibernate中inverse的作用** `inverse`属性用于指定关联关系的维护方,即哪一方负责更新关联关系。 **12. hibernate中对象的三种状态** -...

    inverse=true的总结

    在IT行业中,尤其是在Java开发或者使用ORM框架(如Hibernate)时,“inverse=true”是一个非常重要的概念,它涉及到对象关系映射中的数据管理策略。本文将深入解析“inverse=true”的含义,以及它在实际应用中的作用...

    Hibernate学习笔记和资料

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

    JAVA面试题目

    - **解析:** `inverse`和`cascade`是Hibernate中管理关联关系时使用的两个重要属性: - **inverse**:指定由哪一方负责维护关联关系。在双向关联中,通常一方设置为`true`,另一方设置为`false`。 - **cascade**...

    Hibernate 简单 PPT 总结

    在Hibernate中,`inverse`属性是一个关键的概念,它用于定义一对多或多对一关系中的维护端。`inverse="true"`表示另一端负责维护关联关系,这在处理关联实体的保存和更新时具有重要意义。例如,如果你有一个学生类和...

    hibernate

    根据提供的文件信息,我们可以深入探讨Hibernate框架中的几个关键概念,特别是`fetch`, `lazy`, `cascade`, 和 `inverse`关键字的使用与理解。这四个概念在处理对象关系映射(ORM)时非常重要,尤其是在Java环境下...

Global site tag (gtag.js) - Google Analytics