通过Hibernate Inverse的设置来决定是由谁来维护表和表之间的关系。最近有朋友问我Hibernate关于多对多关于删除中间表数据的问题,关键是Inverse的设置,下面引用网友的一篇文章。
Inverse是Hibernate双向关系中的基本概念,当然对于多数实体,我们并不需要双向关联,更多的可能会选择单向关联,况且我们大多数人 一般采用一对多关系,而一对多双向关联的另一端:多对一的Inverse属性是不存在,其实它默认就是Inverse=false.从而防止了在一对多端 胡乱设置Inverse也不至于出错。但是Inverse设置不当确实会带来很大的性能影响,这点是我们必须关注的。
关于inverse和cascade的区别
cascade:设置级联
sava-update:级联保存、更新
delete:级联删除
none:不级联,默认值
all:级联保存、更新、删除
inverse:在映射一对多关系时,一般将该属性设置为true,表示表间的关联关系由一方设置,减少update语句,提高性能
这篇文章已经详细分析了Hibernate Inverse设置不当带来的影响:http://www.Hibernate.org/155.html,看了这篇文章,还是很有必要再写下一些总结的:
1)Hibernate Inverse中提及的side其实是指一个类或者表的概念,双向关联其实是指双方都可以取得对方的应用。
2)维护关系这个名词还是稍显模糊或者晦涩。我们一般说A类或者A表(这里的表的是指多对多的连接表)有责任维护关系,其实这里的意思是说,我在应 用在更新,创建,删除(读就不用说了,双向引用正是为了方便读而出现)A类或者A表时,此时创建的SQL语句必须有责任保证关系的正确修改。
3)Inverse=false的side(side其实是指Inverse=false所位于的class元素)端有责任维护关系,而Inverse=true端无须维护这些关系。
4)我们说Hibernate 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建立多对多关系也是将他们分离成两个一对多关系,中间连接一 个连接表。所以通用存在一对多的关系,也可以这样说:一对多是多对多的基本组成部分。
看下面的多对多的定义大家更会清楚”多对多“与“一对多”的关系:其中我们注意<many-to-many />标签的特点就知道,它是定义了一个多对多关系,而不是<one-to-many/>。
Xml代码
1.<?xml version="1.0" encoding="UTF-8"?>
2.<!DOCTYPE Hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN" "http://Hibernate.sourceforge.net/Hibernate-mapping-2.0.dtd">
3.<Hibernate-mapping package="org.Hibernate.auction">
4. <class name="TestA" table="TestA" dynamic-update="true"
5. dynamic-insert="true">
6. <id name="id" column="id" type="int" unsaved-value="any">
7. <generator class="assigned">
8. </generator>
9. </id>
10. <property name="name" type="java.lang.String" update="true"
11. insert="true" column="name" />
12. <set name="testBs" table="TestA_TestB" Inverse="false" cascade="all">
13. <key column="testA" />
14. <many-to-many column="testB" class="TestB" />
15. </set>
16. </class>
17. <class name="TestB" table="TestB" dynamic-update="true"
18. dynamic-insert="true">
19. <id name="id" column="id" type="int" unsaved-value="any">
20. <generator class="assigned">
21. </generator>
22. </id>
23. <property name="name" type="java.lang.String" update="true"
24. insert="true" column="name" />
25. <set name="testAs" table="TestA_TestB" Inverse="true" cascade="all">
26. <key column="testB" />
27. <many-to-many column="testA" class="TestA" />
28. </set>
29. </class>
30.</Hibernate-mapping>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN" "http://Hibernate.sourceforge.net/Hibernate-mapping-2.0.dtd">
<Hibernate-mapping package="org.Hibernate.auction">
<class name="TestA" table="TestA" dynamic-update="true"
dynamic-insert="true">
<id name="id" column="id" type="int" unsaved-value="any">
<generator class="assigned">
</generator>
</id>
<property name="name" type="java.lang.String" update="true"
insert="true" column="name" />
<set name="testBs" table="TestA_TestB" Inverse="false" cascade="all">
<key column="testA" />
<many-to-many column="testB" class="TestB" />
</set>
</class>
<class name="TestB" table="TestB" dynamic-update="true"
dynamic-insert="true">
<id name="id" column="id" type="int" unsaved-value="any">
<generator class="assigned">
</generator>
</id>
<property name="name" type="java.lang.String" update="true"
insert="true" column="name" />
<set name="testAs" table="TestA_TestB" Inverse="true" cascade="all">
<key column="testB" />
<many-to-many column="testA" class="TestA" />
</set>
</class>
</Hibernate-mapping> 在对多对中,因为一端维护关系另一端不维护关系的原因,我们必须注意避免在应用中用不维护关系的类建立关系,因为这样建立的关系是不会在数据库中存储的。基于上面的映射文件代码给出一个例子:
Java代码
1.package org.Hibernate.auction;
2.
3.import java.util.*;
4.
5./**
6. * * @author Administrator * * To change the template for this generated type
7. * comment go to * Window>Preferences>Java>Code Generation>Code and
8. * Comments
9. */
10.public class TestA {
11. int id;
12. String name;
13. Set testBs = new HashSet();
14.
15. public TestA() {
16. }
17.
18. public TestA(int id) {
19. setId(id);
20. }
21.
22. public int getId() {
23. return id;
24. }
25.
26. public void setId(int id) {
27. this.id = id;
28. }
29.
30. public String getName() {
31. return name;
32. }
33.
34. public void setName(String name) {
35. this.name = name;
36. }
37.
38. public Set getTestBs() {
39. return testBs;
40. }
41.
42. public void setTestBs(Set s) {
43. testBs = s;
44. }
45.
46. public void addTestB(TestB tb) {
47. testBs.add(tb);
48. }
49.
50. public static void main(String[] args) {
51. }
52.}
53.
54.public class TestB {
55. int id;
56. String name;
57. Set testAs = new HashSet();
58.
59. public TestB() {
60. }
61.
62. public TestB(int id) {
63. setId(id);
64. }
65.
66. public int getId() {
67. return id;
68. }
69.
70. public void setId(int id) {
71. this.id = id;
72. }
73.
74. public String getName() {
75. return name;
76. }
77.
78. public void setName(String name) {
79. this.name = name;
80. }
81.
82. public Set getTestAs() {
83. return testAs;
84. }
85.
86. public void setTestAs(Set s) {
87. testAs = s;
88. }
89.
90. public void addTestA(TestA ta) {
91. testAs.add(ta);
92. }
93.
94. public static void main(String[] args) {
95. }
96.}
package org.Hibernate.auction;
import java.util.*;
/**
* * @author Administrator * * To change the template for this generated type
* comment go to * Window>Preferences>Java>Code Generation>Code and
* Comments
*/
public class TestA {
int id;
String name;
Set testBs = new HashSet();
public TestA() {
}
public TestA(int id) {
setId(id);
}
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 Set getTestBs() {
return testBs;
}
public void setTestBs(Set s) {
testBs = s;
}
public void addTestB(TestB tb) {
testBs.add(tb);
}
public static void main(String[] args) {
}
}
public class TestB {
int id;
String name;
Set testAs = new HashSet();
public TestB() {
}
public TestB(int id) {
setId(id);
}
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 Set getTestAs() {
return testAs;
}
public void setTestAs(Set s) {
testAs = s;
}
public void addTestA(TestA ta) {
testAs.add(ta);
}
public static void main(String[] args) {
}
} 测试代码:
Java代码
1. public void doTest() throws Exception {
2. TestA a1 = new TestA(1);
3. TestA a2 = new TestA(2);
4. TestA a3 = new TestA(3);
5. TestB b1 = new TestB(1);
6. TestB b2 = new TestB(2);
7. TestB b3 = new TestB(3);
8. a1.addTestB(b1);
9. a1.addTestB(b2);
10. a1.addTestB(b3);
11. b2.addTestA(a1);
12. b2.addTestA(a2);
13. Session s = factory.openSession();
14. s = factory.openSession();
15. Session session = factory.openSession();
16. session.save(a1);
17. session.flush();
18. session.close();
19. }
public void doTest() throws Exception {
TestA a1 = new TestA(1);
TestA a2 = new TestA(2);
TestA a3 = new TestA(3);
TestB b1 = new TestB(1);
TestB b2 = new TestB(2);
TestB b3 = new TestB(3);
a1.addTestB(b1);
a1.addTestB(b2);
a1.addTestB(b3);
b2.addTestA(a1);
b2.addTestA(a2);
Session s = factory.openSession();
s = factory.openSession();
Session session = factory.openSession();
session.save(a1);
session.flush();
session.close();
} 测试后连接表的数据为:
testa testb
1 1
1 2
1 3
根据Inverse规则,对这些代码:b2.addTestA(a1); b2.addTestA(a2); 建立的关系,数据库并没有存储下来,因为TestB没有责任维护这些关系,所以产生的sql语句自然不会有针对Testa_testB表的操作了。假设应 用中真的需要这些方法,那么我们可以修改TestB的方法,让他们注意在维护端类中执行相应的操作以使得关系能够在数据库中保存下来,更改TestB如 下:
Java代码
1./* * Created on 2004-7-25 * * To change the template for this generated file go to * Window>Preferences>Java>Code Generation>Code and Comments */package org.Hibernate.auction;
2.
3.import java.util.*;
4.
5./**
6. * * @author Administrator * * To change the template for this generated type
7. * comment go to * Window>Preferences>Java>Code Generation>Code and
8. * Comments
9. */
10.public class TestB {
11. int id;
12. String name;
13. Set testAs = new HashSet();
14.
15. public TestB() {
16. }
17.
18. public TestB(int id) {
19. setId(id);
20. }
21.
22. public int getId() {
23. return id;
24. }
25.
26. public void setId(int id) {
27. this.id = id;
28. }
29.
30. public String getName() {
31. return name;
32. }
33.
34. public void setName(String name) {
35. this.name = name;
36. }
37.
38. public Set getTestAs() {
39. return testAs;
40. }
41.
42. public void setTestAs(Set s) {
43. testAs = s;
44. }
45.
46. public void addTestA(TestA ta) {
47. testAs.add(ta);
48. ta.addTestB(this);
49. }
50.
51. public static void main(String[] args) {
52. }
53.}
/* * Created on 2004-7-25 * * To change the template for this generated file go to * Window>Preferences>Java>Code Generation>Code and Comments */package org.Hibernate.auction;
import java.util.*;
/**
* * @author Administrator * * To change the template for this generated type
* comment go to * Window>Preferences>Java>Code Generation>Code and
* Comments
*/
public class TestB {
int id;
String name;
Set testAs = new HashSet();
public TestB() {
}
public TestB(int id) {
setId(id);
}
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 Set getTestAs() {
return testAs;
}
public void setTestAs(Set s) {
testAs = s;
}
public void addTestA(TestA ta) {
testAs.add(ta);
ta.addTestB(this);
}
public static void main(String[] args) {
}
} 那么测试执行后连接表的数据为:
testa testb
1 2
1 3
1 1
2 2
测试通过。
分享到:
相关推荐
本文将深入探讨Hibernate中的一对多关系,并重点解析`inverse`属性的作用及其应用。 一对多关系是数据库设计中常见的关联类型,例如一个用户可以拥有多个订单,一个班级可以包含多个学生等。在Hibernate中,通过...
Hibernate中cascade与inverse属性详解
### Hibernate Inverse 和 Cascade 的详细讲解 #### 一、引言 在ORM(Object-Relational Mapping)领域,Hibernate作为一款流行的Java持久层框架,它提供了丰富的API和配置选项来帮助开发者实现对象与数据库表之间...
Hibernate 配置文件详解 Hibernate 是一个流行的 ORM(Object-Relational Mapping)框架,用于简化 Java 应用程序中的数据库交互。 Hibernate 的配置文件是其核心组件之一,用于定义 Hibernate 的运行期参数。下面...
### Hibernate配置详解(二)——深入理解`.hbm.xml`文件与实体关联 #### 引言 在前文《Hibernate 配置详解》中,我们已经初步探讨了Hibernate框架的基本配置,包括`hibernate.cfg.xml`文件的重要性及其在...
Spring集成Struts与Hibernate入门详解 Spring框架是Java平台上一个开源的轻量级框架,它提供了许多功能强大且灵活的模块,以帮助开发者快速构建企业级应用程序。Struts是Apache软件基金会的一个开源项目,提供了一...
在深入探讨Hibernate集合映射中的`inverse`与`cascade`属性之前,我们首先需要理解Hibernate框架的基本概念。Hibernate是一个开放源代码的对象关系映射(ORM)框架,它为Java应用程序提供了一种将对象模型与数据库...
### Hibernate常用注解详解 #### 一、JPA与Hibernate注解基础 JPA(Java Persistence API)是一种标准规范,用于实现对象关系映射(ORM),允许开发人员使用注解或XML来描述实体对象与数据库表之间的映射关系。...
**Hibernate对象关系详解** 在Java世界中,Hibernate作为一款强大的对象关系映射(ORM)框架,使得开发者可以方便地在Java对象与数据库表之间进行数据操作。本篇将深入探讨Hibernate中的对象关系映射,包括一对一...
### Hibernate映射关联详解 #### 一、理解一对多双向关联关系 在关系型数据库设计中,一对多关联是常见的数据组织方式之一。而在面向对象编程语言中,这种关系则通常通过集合(如Set或List)来实现。本文将重点...
hibernate概述,hibernate入门Demo,hibernate配置文件详解(全局配置,实体类映射配置),配置实体规则,核心API详解(Configuration,sessionFactory,session,Transaction),hibernate中的对象状态以及刷新能缓存机制 ...
2.4.1 Hibernate的核心接口 2.4.2 事件处理接口 2.4.3 Hibernate映射类型接口 2.4.4 可供扩展的接口 2.5 小结 2.6 思考题 第3章 第一个Hibernate应用 3.1 创建Hibernate的配置文件 3.2 创建持久化类...
以下是对Hibernate一对多映射配置的详解: 一、XML文件配置 1. 单向关联 在这种配置中,关系只在一个方向上定义,例如User类有多个Account。在User的配置文件中,不直接声明与Account的关联,而是在Account的配置...
【Hibernate配置文件中映射元素详解】 在对象关系映射(ORM)框架Hibernate中,对象与数据库表之间的关联是通过一个XML配置文件来定义的。这个XML文件包含了映射元素,用于描述Java类如何转化为数据库中的表。映射...
### Hibernate开发指南知识点详解 #### 一、简介与概述 **标题:“hibernate夏昕.pdf内容全面通俗易懂”** - **主要内容**: 本文档是夏昕针对Hibernate框架的一份开发指南,内容覆盖了Hibernate的基本概念、核心...
【Hibernate关键知识点详解】 Hibernate是一款强大的Java持久化框架,它为开发者提供了在关系数据库与对象模型之间进行映射的能力,从而简化了数据访问层的开发。在这个知识点大全中,我们将深入探讨Hibernate的...
5. `set`:用于一对多的关系映射,`inverse`属性表示维护关系的责任方,`order-by`可以指定排序依据,`key`元素定义了集合元素的外键列。 6. `one-to-many`:定义了多的一方,`class`属性是目标类的完全限定名。 ...
**Hibernate 结构框架详解** Hibernate 是一款流行的 Java ORM(对象关系映射)框架,它允许开发者将数据库操作转化为对 Java 对象的操作,简化了数据库应用的开发。在深入分析 Hibernate 结构框架之前,我们先来...