彻底明白Hibernate中的Inverse的含义
来源:互联网 发布:网络时钟系统 编辑:程序博客网 时间:2024/06/07 01:43
其实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这个属性打开,然后观察一下就知道了)
接下来再看看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”方负责的,而这里恰恰被注释了)。
{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/}
Child c = new Child();
p.getChildren().add(c);
c.setParent(p);
session.save(c);
session.flush();
Hibernate: insert into child (parent_id, id) values (?, ?)
Hibernate: update child set parent_id=? where id=?
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);
c.setParent(p2);
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: update child set parent_id=null where parent_id=? //remove
Hibernate: update child set parent_id=? where id=? // add
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);
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=?
小结:使用“inverse=true”可以优化代码,同时,推荐在建立双向关系的时候使用“inverse=true”!
此文章也时喝nhibernate开发的一些问题!
- 彻底明白Hibernate中的Inverse的含义
- 彻底明白Hibernate中的Inverse
- 彻底明白Hibernate中的Inverse
- 彻底明白Hibernate中的Inverse
- 彻底明白Hibernate中的Inverse
- 彻底明白Hibernate中的Inverse
- 彻底明白Hibernate中的Inverse
- 彻底明白Hibernate中的Inverse
- zz彻底明白Hibernate中的Inverse(一)
- 彻底明白Hibernate中的Inverse(二)-zz
- 彻底明白Hibernate中的Inverse修正版
- 彻底明白IP地址的含义
- Hibernate的关键字inverse的含义
- hibernate中的inverse的用法
- 彻底搞明白find命令的-mtime参数的含义
- Hibernate中的inverse
- hibernate中的Inverse作用
- hibernate中的Inverse
- aptana 1的破解方法
- 网络基本知识
- Discuz!NT控件剖析 之 Button [原创: 附源码]
- 程序员面试题精选(45):求给定整数其二进制形式含1的个数
- 李阳疯狂英语突破对话(65)-在邮局
- 彻底明白Hibernate中的Inverse的含义
- 关于文件操作的API函数
- HttpClient和HtmlParser配合实现自动登陆系统抽取页面信息
- jsp的九大内置对象
- [英语阅读]电脑游戏的历史
- 理解HTTP session原理及应用
- VC透明窗体的实现
- js技巧收集(200多个)
- WinCE系统音量的设置