`
klcwt
  • 浏览: 194654 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

cacade inverse

    博客分类:
  • java
阅读更多
hibernate 中inverse cascade属性(转)
在hibernate中一对多关联时会经常用到inverse和cascade属性 ,
inverse 有两个值 true ,false  ;如果设置为true 则表示对象的状态变化不会同步到数据库 ;设置false就相反拉;
cascade 有五个选项 分别是: all ,delete ,none,save-update,delete-orphan ;
        all : 所有情况下均进行关联操作。
        none:所有情况下均不进行关联操作。这是默认值。
        save-update:在执行save/update/saveOrUpdate时进行关联操作。
        delete:在执行delete时进行关联操作。
        delete-orphan: 当save/update/saveOrUpdate时,相当于save-update ;当删除操作时,相当于delete ;


all的意思是save-update + delete
all-delete-orphan 的意思是当对象图中产生孤儿节点时,在数据库中删除该节点
all比较好理解,举个例子说一下all-delete-orphan:
Category与Item是一对多的关系,也就是说Category类中有个Set类型的变量items.
举个例子,现items中存两个Item, item1,item2,如果定义关系为all-delete-orphan
当items中删除掉一个item(比如用remove()方法删除item1),那么被删除的Item类实例
将变成孤儿节点,当执行category.update(),或session.flush()时
hibernate同步缓存和数据库,会把数据库中item1对应的记录删掉




测试Hibernate中的三个属性:lazy,inverse,cascade

【测试环境】
一对多关系的两张表:boy、girl(一个男孩可以多个女朋友)

boy表结构
Field   Type       
------  -----------
name    varchar(50)  pk
age     varchar(50)

girl表结构
Field   Type       
------  -----------
name    varchar(50)  pk
bf      varchar(50)  fk

ER图



【保存时:Inverse与cascade】

创建三个girl对象和一个boy对象,让这是三个girl都是boy的女朋友


  ---------创建对象的代码片段-----------
  Boy boy = new Boy("tom","23", null);

  Set girls = new HashSet();
 
  Girl g[] = new Girl[]{
                        new Girl("Alice1", boy),
                        new Girl("Alice2", boy),
                        new Girl("Alice3", boy)};
  girls.add(g[0]);
  girls.add(g[1]);
  girls.add(g[2]);
 
  boy.setGirls(girls);

在Boy.hbm.xml中设置,然后对boy对象进行保存。

1.Inverse = true,不指定cascade
   cascade的默认值为none, 当对boy进行保存操作时,girl什么都不做. 所以只保存了boy对象, 没有保存girl对象

2.Inverse = true,cascade=all
   boy与girl对象,包扩外键都成功保存。
   (生成3条SELECT语句和4条INSERT语句,一下简称SELECT 3, INSERT 4)

3.Inverse = false,不指定cascade
   报错。因为boy为主控方,负责维护关系,所以在插入boy对象后,会尝试修改并不存在的girl对象。

4.Inverse = false,cascade=all
   boy与girl对象,包扩外键都成功保存。
   (SELECT 4, INSERT 4, UPDATE 3)

   分析:除了4条INSERT语句之外,其他的6条语句是我们为了图方便付出的代价:3条SELECT语句用来判断girl对象是否在数据表中已经存在,3条UPDATE语句是为了维护外键关系

高效率的做法:在Boy.hbm.xml中设置Inverse=true,在Girl.hbm.xml中设置Inverse=false, cascade=all,然后保存三个girl对象
(SELECT 1, INSERT 4)

   高效率的代价就是保存的时候比较麻烦

【删除时:Inverse与cascade】

希望通过删除boy,也将3个girl对象删除。程序中先查出boy对象,然后进行删除
  -----------------------------------------
  Boy boy = (Boy) s.get(Boy.class, "tom");
  s.delete(boy);
  -----------------------------------------


同样在Boy.hbm.xml中进行设置

1.Inverse = true
   可以猜到结果是出错。原因:外键约束错误

2.Inverse = false
   boy删除,girl表中外键变为null,没有删除记录 ; 
(UPDATE 1, DELETE 1)

3.Inverse = false, cascade = all
          全部删除  ;在删除有外键的从表时,先把从表外键置为null,然后删除主表记录,最后根据从表主键删除所有相关从表记录

   (UPDATE 1, DELETE 4)

4.Inverse = true, cascade = all
          全部删除
   (DELETE 4)


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

测试通过。


分享到:
评论

相关推荐

    NHibernate Inverse & Cascade

    "NHibernate Inverse & Cascade"是两个关键概念,对于理解和有效使用NHibernate至关重要。 **Inverse属性** Inverse属性主要用于控制NHibernate如何处理关联对象的持久化。在一对多或多对一的关系中,当一个实体...

    inverse=true的总结

    在IT行业中,尤其是在Java开发或者使用ORM框架(如Hibernate)时,“inverse=true”是一个非常重要的概念,它涉及到对象关系映射中的数据管理策略。本文将深入解析“inverse=true”的含义,以及它在实际应用中的作用...

    inverse_c语言inverse_inverse在C_cinverse_c语言longinverse_反插值_

    在这个主题中,我们关注的是一个使用C语言实现的反插值程序,名为"inverse",它似乎对常规的反插值方法进行了优化,加入了正则化处理,以提高计算效果。 首先,让我们理解什么是反插值。在插值中,我们通常有一个...

    inverse 例子

    在Hibernate这个强大的对象关系映射(ORM)框架中,`inverse`属性是一个非常重要的概念,它主要用于管理关联关系的维护责任。在这个例子中,我们将会深入理解`inverse`属性的作用,并通过一个简单的测试案例——`...

    彻底明白Hibernate中的Inverse

    在Hibernate中,`Inverse`是一个重要的概念,它涉及到实体之间的关联管理。本文将深入探讨`Inverse`属性,以及它在Hibernate中的作用和应用场景。 一、Hibernate与对象关系映射 Hibernate通过ORM机制将Java对象与...

    hibernate inverse和cascade的详细讲解

    ### Hibernate Inverse 和 Cascade 的详细讲解 #### 一、引言 在ORM(Object-Relational Mapping)领域,Hibernate作为一款流行的Java持久层框架,它提供了丰富的API和配置选项来帮助开发者实现对象与数据库表之间...

    inverse和cascade使用阐述

    在IT领域,"inverse"和"cascade"是两个常见的概念,尤其在数据库设计、软件工程以及数据处理中。这两个术语通常与关系型数据库中的外键约束、对象关系映射(ORM)工具,以及某些编程框架的特性相关。下面将详细阐述这...

    IND Inverse - MetaTrader 4脚本.zip

    "IND Inverse - MetaTrader 4 脚本.zip" 是一个包含 MetaTrader 4 (MT4) 平台使用的自定义指标的压缩文件。这个指标被称为 "IND Inverse Indicator",它专为外汇交易者设计,帮助他们在市场分析中做出更明智的决策。...

    MVC映射inverse

    在Java的ORM框架如Hibernate中,`inverse`属性是一个关键的概念,主要用于管理一对多或多对一关联关系的主键维护。在这个例子中,我们讨论的是`inverse`在一对多双向关联关系中的应用,涉及两个实体类:`Student`和`...

    Inverse heat conduction ill-posed problems

    Inverse heat conduction ill-posed problems

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

    本文将深入探讨Hibernate中的一对多关系,并重点解析`inverse`属性的作用及其应用。 一对多关系是数据库设计中常见的关联类型,例如一个用户可以拥有多个订单,一个班级可以包含多个学生等。在Hibernate中,通过...

    PARAMETER ESTIMATION AND INVERSE PROBLEMS(2013)

    This textbook evolved from a course in geophysical inverse methods taught during the past two decades at New Mexico Tech, first by Rick Aster and, subsequently, jointly between Rick Aster and Brian ...

    Hibernate中cascade与inverse属性详解

    Hibernate中cascade与inverse属性详解

    Parameter estimation and inverse problems

    在科学和工程领域中,参数估计与反问题(Parameter Estimation and Inverse Problems)是解决实际问题的重要工具之一。这类问题通常涉及未知参数或状态的确定,这些参数或状态无法直接测量,但可以通过观察到的数据...

    COMPUTATIONAL METHODS FOR INVERSE PROBLEMS

    COMPUTATIONAL METHODS FOR INVERSE PROBLEMS,反问题的计算方法,国外艾斯维尔出版的关于反问题求解的重要书籍,JPG版本

    Inverse Problem Theory and Methods for Model Parameter Estimation

    **标题:** "Inverse Problem Theory and Methods for Model Parameter Estimation"(反演问题理论与模型参数估计方法) 此书名表明了该书的核心内容是关于反演问题的理论及其在模型参数估计中的应用方法。反演问题...

    Discrete Inverse Problems, Insight and Algorithms.pdf清晰版

    ### 知识点一:离散反问题的基本概念 **离散反问题**是指一类在数学建模过程中遇到的问题,这些问题通常与从观测数据中恢复未知源或过程有关。这类问题之所以被称为“反问题”,是因为它们是相对于正向(直接)问题...

Global site tag (gtag.js) - Google Analytics