在hibernate中是通过inverse的设置来决定是有谁来维护表和表之间的关系的
最近有朋友问我hibernate关于多对多关于删除中间表数据的问题,关键是inverse的设置.下面引用网友的一篇文章
Inverse是hibernate双向关系中的基本概念,当然对于多数实体,我们并不需要双向关联,更多的可能会选择单向关联,况且我们大多数人一般采用一对多关系,而一对多双向关联的另一端:多对一的inverse属性是不存在,其实它默认就是inverse=false.从而防止了在一对多端胡乱设置inverse也不至于出错。但是inverse设置不当确实会带来很大的性能影响,这点是我们必须关注的。
这篇文章已经详细分析了inverse设置不当带来的影响:
http://www.hibernate.org/155.html
看了这篇文章,还是很有必要再写下一些总结的:
1)inverse中提及的side其实是指一个类或者表的概念,双向关联其实是指双方都可以取得对方的应用。
2)维护关系这个名词还是稍显模糊或者晦涩。我们一般说A类或者A表(这里的表的是指多对多的连接表)有责任维护关系,其实这里的意思是说,我在应用在更新,创建,删除(读就不用说了,双向引用正是为了方便读而出现)A类或者A表时,此时创建的SQL语句必须有责任保证关系的正确修改。
3)inverse=false的side(side其实是指inverse=false所位于的class元素)端有责任维护关系,而inverse=true端无须维护这些关系。
4)我们说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 version="1.0"?>
<!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>
在对多对中,因为一端维护关系另一端不维护关系的原因,我们必须注意避免在应用中用不维护关系的类建立关系,因为这样建立的关系是不会在数据库中存储的。基于上面的映射文件代码给出一个例子:
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) {
}
}
测试代码:
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如下:
/*
* 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
测试通过。
分享到:
相关推荐
多对多双向关联 <br>注意映射规则: <set name="roles" table="t_user_role"><br> <key column="userid"/><br> <many-to-many class="com.bjsxt.hibernate.Role" column="roleid"/> </set><br> table...
总结来说,理解并合理运用Hibernate中的`Inverse`属性对于优化数据操作、提高代码可读性和维护性具有重要意义。通过精确控制关联的维护责任,我们可以更好地管理对象关系,实现高效且一致的数据库操作。
总之,理解并正确实现Hibernate中的一对多双向关联映射是提升应用程序性能和数据一致性的重要步骤。通过细心配置映射文件,编写相应的实体类,以及妥善处理关联关系的维护,我们可以有效地管理复杂的数据结构。
为了使双向关联正常工作,还需要在Java代码中进行相应的设置。例如,在创建新订单时,不仅要设置订单的用户属性,也要在用户对象的订单集合中添加该订单: ```java User user = new User(); Order order = new ...
理解JPA中一对一双向关联的实现,你可以查看Hibernate(一个流行的JPA实现)的源码,学习其内部如何处理关联的建立和维护。同时,使用诸如IntelliJ IDEA这样的集成开发环境(IDE),其内置的代码生成器可以帮助你...
标题"Hibernate双向一对多"指的是Hibernate框架中的一个重要关系映射概念,即在一个实体类中,一个实例可以与多个另一个实体类的实例相关联,而在另一个实体类中,每个实例也可以关联到该实体类的一个实例。...
在一个双向关联中,如果一方设为inverse="true",意味着这一方不负责维护关联关系。以用户和订单为例,如果User对象设置为inverse,那么更新Order对象的User引用时,Hibernate不会更新数据库中的关联关系。相反,...
本篇文章将深入探讨 Hibernate 中的一对多双向关联映射。 在数据库设计中,一对多关联是指一个实体可以与多个其他实体相关联,比如一个学生可以有多个课程,一个部门可以有多名员工。在Hibernate中,这种关系可以...
最后,实践是检验理论的最好方式,你可以参考提供的压缩包文件`hibernate_1700_many2many_bidirectional`,里面可能包含了示例代码和测试用例,通过实际运行和调试加深对Hibernate多对多双向关联的理解。通过这种...
除了单向关联,还可以建立双向关联,例如在学生类中添加对班级的引用。在映射文件中使用`<many-to-one>`标签定义。 6. 多对多关联(Many-to-Many): 如课程与教师之间的关系,通常需要通过一个中间表来实现。...
如果是双向关联,其中一段必须定义为Owner,另一端必须定义为inverse(在对关联表进行更新操作时这一端将被忽略) @Entity() public class Employer implements Serializable { private Integer id; private ...
总之,理解和熟练运用Hibernate的一对多、多对一以及双向关联,是提升Java企业级应用开发效率的关键。通过注解或XML配置,开发者可以灵活地定义实体间的关联,实现数据的持久化。同时,注意级联操作、懒加载策略等...
正确理解和使用这些关联映射对于构建高效且易于维护的数据库应用程序至关重要。无论是单向还是双向映射,了解其背后的工作原理和实现细节都将有助于开发者更好地设计和优化其数据模型。希望本文能够为初学者提供一个...
`inverse="true"`属性指明了该关系是由另一端维护的,这在双向关联中很重要,因为它决定了关系的维护方向,防止在两个实体间形成循环依赖。 ### 三、逆向关联的理解 在一对多双向关联中,通常会有一个实体负责维护...
在Hibernate框架中,双向一对多关联映射是常见的对象关系映射(ORM)方式,用于在Java对象模型中表示数据库中的两个实体之间的多对一关系。在这个场景中,"一"端通常指的是一个实体可以拥有多个另一个实体的实例,而...
本篇将详细讲解如何在Hibernate中实现一对多的双向关联,并提供相关的代码示例。 在关系型数据库中,一对多关联是指一个表的记录可以对应另一个表的多个记录。在Hibernate中,这种关系可以通过在实体类和映射文件中...
- **双向关联**:在两个实体的映射文件中都需要`<many-to-many>`标签,并且需要一个共享的中间表。 关联映射的配置涉及到`cascade`属性,它决定了级联操作的行为,如`save-update`、`delete`等。`inverse`属性则...
3. 管理关联:在双向一对多关系中,如果不设置`inverse`,Hibernate会认为两个方向的关联都需要维护,这可能导致不必要的数据库更新,降低性能。通过合理设置`inverse`,可以避免这种情况,提高效率。一般做法是将`...
单向关联仅在一个实体类中定义,而双向关联则在两个实体类中都有相应的引用。 **配置一对多关联** 1. **XML配置**:在`hbm.xml`文件中,使用`<set>`或`<list>`元素来定义一对多关联。例如: ```xml ... ...
#### 一、理解一对多双向关联关系 在关系型数据库设计中,一对多关联是常见的数据组织方式之一。而在面向对象编程语言中,这种关系则通常通过集合(如Set或List)来实现。本文将重点探讨如何在Hibernate框架下实现...