`
kangsg219
  • 浏览: 123122 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

正确理解hibernate的inverse! many-to-many(转载)

阅读更多

Inverse是hibernate双向关系中的基本概念,当然对于多数实体,我们并不需要双向关联,更多的可能会选择单向关联,况且我们大多数人一般采用一对多关系,而一对多双向关联的另一端:多对一的inverse属性是不存在,其实它默认就是inverse=false.从而防止了在一对多端胡乱设置inverse也不至于出错。但是inverse设置不当确实会带来很大的性能影响,这点是我们必须关注的。

这篇文章已经详细分析了inverse设置不当带来的影响:

http://www.hibernate.org/155.html   (这个链接已经无效了,直接看下面的也可以使你能够较好的理解hibernate的inverse)

看了这篇文章,还是很有必要再写下一些总结的:

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建立多对多关系也是将他们分离成两个一对多关系,中间连接一个连接表。所以通用存在一对多的关系,也可以这样说:一对多是多对多的基本组成部分。

看下面的多对多的定义大家更会清楚”多对多“与“一对多”的关系:其中我们注意标签的特点就知道,它是定义了一个多对多关系,而不是<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

测试通过。
========原文地址:http://blog.csdn.net/soleghost/archive/2005/10/27/517873.aspx
分享到:
评论

相关推荐

    Hibernate one-to-many / many-to-one关系映射

    总结,Hibernate的one-to-many和many-to-one关系映射是数据库对象关联的基础,理解和熟练掌握它们能帮助开发者更高效地设计和实现Java持久化层。通过合理的配置和实践,可以构建出高性能、易于维护的数据访问层。

    Hibernate Mapping Many-to-One 实例 内附源代码及附件下载

    通过研究这个例子,你可以更深入地理解如何在实际开发中设置和使用Many-to-One关系。 总的来说,Hibernate的Many-to-One映射简化了数据库关系的处理,使得开发者可以专注于业务逻辑,而不是繁琐的SQL操作。通过这个...

    hibernate学习5之one-to-many双向关联.docx

    在配置双向一对多关联时,我们通常在"多"一端(这里是`Student`)的集合属性上使用`&lt;many-to-one&gt;`标签,将`Classes`对象映射到数据库中的外键。同时,在"一"端(`Classes`)使用`&lt;set&gt;`标签,表示班级可以包含多个...

    Hibernate-one-to-many

    本文将深入探讨Hibernate中一对多(One-to-Many)关系的处理方式,特别是通过外键映射和inverse属性的应用场景。 #### 一对多关系概念 一对多关系在数据库设计中非常常见,它指的是一个实体可以与多个其他实体关联...

    hibernate inverse和cascade的详细讲解

    - **适用场景**:`inverse`仅适用于`one-to-many`或`many-to-many`关系,因为这两种关系包含了集合。对于`one-to-one`和`many-to-one`关系,它们仅包含单个对象的引用,因此不需要使用`inverse`。 - **Inverse 的...

    hibernate配置文件详解

    &lt;one-to-many class="com.Hibernate.City" /&gt; &lt;/hibernate-mapping&gt; ``` 在该文件中,我们可以看到有多个关键的配置项: * `class`:定义类名和对应的数据库表名 * `id`:定义类的主键信息 * `property`:...

    hibernate中many2many映射

    在Java持久化框架Hibernate中,Many-to-Many(多对多)映射是一种常见的关联关系类型,用于表示两个实体类之间复杂的关系。在本场景中,我们探讨的是如何在Hibernate中配置Many-to-Many映射,并使用MySQL数据库来...

    hibernate的关联映射

    关联映射主要包括四种类型:一对一(One-to-One)、一对多(One-to-Many)、多对一(Many-to-One)和多对多(Many-to-Many)。下面我们将逐一探讨这些关联映射的配置方法。 1. **一对一关联映射** - **主键关联**...

    Hibernate持久化映射一对多和多对一

    本文将深入探讨Hibernate中的两个重要概念:一对多(One-to-Many)和多对一(Many-to-One)的持久化映射。 ### 一对多映射 **定义**: 一对多映射表示一个实体(如部门)可以关联多个实体(如员工)。在数据库层面...

    hibernate中one2many映射

    在Java的持久化框架Hibernate中,One-to-Many映射是一种常见的关系映射方式,它表示一个实体(比如一个用户)可以与多个其他实体(比如用户的订单)进行关联。在这个场景下,"用户"是一方,称为"One","订单"是另...

    hibernate map 集合映射

    &lt;many-to-many column="FRIEND_ID" class="com.example.User"/&gt; ``` ```xml &lt;!-- Friend.hbm.xml --&gt; &lt;set name="friends" table="USER_FRIENDS" inverse="true"&gt; &lt;many-to-many column="USER_ID" class=...

    hibernate 全面学习->hibernate 关联映射学习

    本篇文章将全面探讨Hibernate的关联映射学习,包括一对一(One-to-One)、一对多(One-to-Many)、多对一(Many-to-One)以及多对多(Many-to-Many)四种关系映射。 首先,一对一关联映射(One-to-One)是两个实体...

    NHibernate One-to-Many一对多映射-xxlinux_com

    在数据库世界中,一对多(One-to-Many)关系是一种常见的关联类型,其中一个表(父表)可以与多个其他表(子表)相关联。在NHibernate中,配置这种映射关系对于理解和使用ORM至关重要。 一对多关系意味着一个实体...

    hibernate的多对多配置

    在Java的持久化框架Hibernate中,多对多(Many-to-Many)关系是数据库中常见的关联类型,允许一个实体实例对应多个其他实体实例,反之亦然。本篇将深入探讨如何在Hibernate中配置多对多关系,特别是通过hibernate....

    Hibernate关联关系配置

    &lt;many-to-one name="customer" class="com.suxiaolei.hibernate.pojos.Customer" column="customer_id" cascade="save-update"&gt; &lt;/many-to-one&gt; &lt;/hibernate-mapping&gt; ``` 在这个配置文件中,`&lt;many-to-one&gt;`...

    Hibernate一对多映射配置详解

    在User的配置文件中,不直接声明与Account的关联,而是在Account的配置文件中通过`&lt;many-to-one&gt;`标签来定义与User的关联。`name`属性指定了关联属性名,`column`属性指定了外键列名,`class`属性指定了关联类的全...

    角色(使用hibernate映射多对多的关系).zip

    在Hibernate中,多对多关系的映射可以通过`&lt;many-to-many&gt;`标签来实现。这个标签位于类的`&lt;class&gt;`元素内部,用于定义两个实体类之间的关联。 1. **关联表**:由于多对多关系需要一个关联表,我们通常需要在...

    Hibernte使用及配置说明

    &lt;one-to-many class="com.entity.Rights"/&gt; &lt;/hibernate-mapping&gt; ``` 通过以上配置和步骤,我们可以利用 Hibernate 快速实现数据库操作,并充分利用其提供的高级功能。这种模式不仅能够提高开发效率,还能...

    Hibernate多对多双向关联(annotation/xml)

    在Java的持久化框架Hibernate中,多对多(Many-to-Many)关联是常见的关系映射类型,尤其在处理数据库中的复杂关系时显得尤为重要。本主题将深入探讨使用Hibernate进行多对多双向关联的实现,既可以通过注解...

    hibernate inverse 个人总结.doc

    在Hibernate中,一对多(One-to-Many)关系是常见的实体关联类型,它描述了一个实体可以与多个其他实体关联。 `inverse`属性是Hibernate中一对多关联映射的一个关键设置,用于控制关联维护的一方。在一对多关系中,...

Global site tag (gtag.js) - Google Analytics