`

正确理解hibernate的inverse

阅读更多

在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&gt;Preferences&gt;Java&gt;Code Generation&gt;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&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
*/
package org.hibernate.auction;
import java.util.*;

/**
* @author Administrator
*
* To change the template for this generated type comment go to
* Window&gt;Preferences&gt;Java&gt;Code Generation&gt;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中的`Inverse`属性对于优化数据操作、提高代码可读性和维护性具有重要意义。通过精确控制关联的维护责任,我们可以更好地管理对象关系,实现高效且一致的数据库操作。

    hibernate inverse 个人总结.doc

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

    hibernate inverse和cascade的详细讲解

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

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

    综上所述,理解并正确使用Hibernate中的`inverse`属性对于优化JavaEE应用的数据库操作和提高代码质量具有重要意义。通过深入掌握这一特性,开发者能够更好地管理对象之间的关联,提升应用的性能和稳定性。

    Hibernate中cascade和inverse应用

    在实际应用中,需要根据业务需求谨慎选择 `cascade` 和 `inverse` 的值,以确保数据的正确性和效率。 总之,`cascade` 和 `inverse` 是 Hibernate 中用来优化对象关系管理的两个关键特性,它们可以帮助开发者更有效...

    hibernate常用注解

    ### Hibernate常用注解详解 #### 一、JPA与Hibernate注解基础 JPA(Java Persistence API)是一种标准规范,用于实现对象关系映射(ORM),允许...理解和熟练掌握这些注解对于使用Hibernate进行持久化操作至关重要。

    inverse=true的总结

    6. 工具应用:在实际开发中,理解并正确使用`inverse=true`能够提高代码的可维护性和性能。开发者应根据业务需求,谨慎选择关联的维护方,并合理配置级联操作,以达到最佳的数据操作效果。 总结,`inverse=true`是...

    Hibernate电子书(全)

    正确设置`inverse`可以确保Hibernate在处理关联关系时的行为符合预期。 #### 一对一与多对多实体映射 Hibernate支持一对一和多对多关系的映射,分别通过`@OneToOne`和`@ManyToMany`注解实现。这些映射策略使得复杂...

    hibernate

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

    hibernate bag 集合映射

    源码分析有助于理解Hibernate的工作原理,而工具可能是简化配置或调试的辅助手段。 在文件名“bagMapping”中,我们可能假设这是一个示例或教程,包含有关如何设置和使用bag映射的配置文件、Java实体类和可能的测试...

    关联映射cascade,inverse讲解

    通过阅读和实践这些代码,你可以更深入地理解Hibernate的关联映射,掌握cascade和inverse的实际应用技巧。 总之,理解并熟练运用Hibernate的关联映射、cascade和inverse是提升Java持久化编程能力的关键步骤。它们...

    Hibernate常见问题

    理解并正确使用Hibernate的`cascade`和`inverse`属性对于优化数据操作和避免数据一致性问题至关重要。在实际开发中,应根据业务逻辑和数据模型谨慎设定这些属性,以确保数据操作的正确性和高效性。

    Hibernate开发指南

    通过学习本书,不仅可以掌握Hibernate的核心技术,还能了解到作者在实际项目中遇到的问题及解决方案,对于深入理解Hibernate及其在企业级应用中的作用具有重要意义。 综上所述,《Hibernate开发指南》覆盖了从基础...

Global site tag (gtag.js) - Google Analytics