hibernate中cascade与inverse讲解

2024-04-13 12:32

本文主要是介绍hibernate中cascade与inverse讲解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这两个属性都用于一多对或者多对多的关系中。而inverse特别是用于双向关系,在单向关系中我们并不需要。

 

Cascade代表是否执行级联操作,Inverse代表是否由己方维护关系。

 

Cascade:

 

Cascade属性的可能值有

    all: 所有情况下均进行关联操作,即save-update和delete。
    none: 所有情况下均不进行关联操作。这是默认值。
    save-update: 在执行save/update/saveOrUpdate时进行关联操作。
    delete: 在执行delete 时进行关联操作。

    all-delete-orphan: 当一个节点在对象图中成为孤儿节点时,删除该节点。比如在一个一对多的关系中,Student包含多个book,当在对象关系中删除一个book时,此book即成为孤儿节点。

 

Inverse:

 

Inverse属性的可能值是true或者false,默认为false:

 

     false代表由己方来维护关系,true代表由对方来维护关系。在一个关系中,只能由一方来维护关系,否则会出问题(解疑中会讲到);同时也必须由一方来维护关系,否则会出现双方互相推卸责任,谁也不管。

 

一多对的例子:

 

有两个类,Father和Child,是一对多的关系。下面这段hbm配置是从Father.hbm.xml中摘取的。

 

 

<set name="children" lazy="true" cascade="all" inverse="true">
<key column="fatherid"/>
<one-to-many class="my.home.Child"/>
</set>  

 

我们知道cascade和inverse的值对会有四种组合的可能(在此仅先假定cascade值为none或all)。

 

有如下一段代码:

 

Java代码 复制代码  收藏代码
  1. FatherDao fatherDao = new FatherDao();   
  2.   
  3. Father father = new Father("David");   
  4. Child child1 = new Child("David Junior One");   
  5. Child child2 = new Child("David Junior Two");   
  6.   
  7. father.add(child1);   
  8. father.add(child2);   
  9.   
  10. fatherDao.save(father);  
FatherDao fatherDao = new FatherDao();
Father father = new Father("David");
Child child1 = new Child("David Junior One");
Child child2 = new Child("David Junior Two");
father.add(child1);
father.add(child2);
fatherDao.save(father);

 

1. 如果cascade="all"且inverse="false"时:

 

此时可以看到log里面:

 

Java代码 复制代码  收藏代码
  1. // 执行对father的插入   
  2. Hibernate: insert into father (name) values (?)   
  3.   
  4. // cascade = 'all',所以进行级联操作   
  5. Hibernate: insert into child (name, fatherid) values (?, ?)   
  6. Hibernate: insert into child (name, fatherid) values (?, ?)   
  7.   
  8. // inverse = 'false',由father来维护关系(可以看到这些操作是多余的)   
  9. Hibernate: update child set fatherid =? where ID=?   
  10. Hibernate: update child set fatherid =? where ID=?  
// 执行对father的插入
Hibernate: insert into father (name) values (?)
// cascade = 'all',所以进行级联操作
Hibernate: insert into child (name, fatherid) values (?, ?)
Hibernate: insert into child (name, fatherid) values (?, ?)
// inverse = 'false',由father来维护关系(可以看到这些操作是多余的)
Hibernate: update child set fatherid =? where ID=?
Hibernate: update child set fatherid =? where ID=?
 

2. 如果cascade = "none" 且 inverse = "false":

 

Java代码 复制代码  收藏代码
  1. // 执行对father的插入   
  2. Hibernate: insert into father (name) values (?)   
  3.   
  4. // inverse='false',所以更新关系   
  5. Hibernate: update child set fatherid =? where ID=?   
  6.   
  7. // 但由于cascade='none',child并未插入数据库,导致如下exception   
  8. org.springframework.dao.InvalidDataAccessApiUsageException: object references an unsaved transient instance  
// 执行对father的插入
Hibernate: insert into father (name) values (?)
// inverse='false',所以更新关系
Hibernate: update child set fatherid =? where ID=?
// 但由于cascade='none',child并未插入数据库,导致如下exception
org.springframework.dao.InvalidDataAccessApiUsageException: object references an unsaved transient instance
 

3. 如果cascade = "all" 且 inverse = "true"

 

Java代码 复制代码  收藏代码
  1. // 执行对father的插入   
  2. Hibernate: insert into father (name) values (?)   
  3.   
  4. // cascade='all',执行对child的插入   
  5. Hibernate: insert into child (name, fatherid) values (?, ?)   
  6. Hibernate: insert into child (name, fatherid) values (?, ?)   
  7.   
  8. // 但由于inverse='true',所以未有对关系的维护。但由于一对多的关系中,关系本身在“多”方的表中。所以,无需更新   
  9. 关系。  
// 执行对father的插入
Hibernate: insert into father (name) values (?)
// cascade='all',执行对child的插入
Hibernate: insert into child (name, fatherid) values (?, ?)
Hibernate: insert into child (name, fatherid) values (?, ?)
// 但由于inverse='true',所以未有对关系的维护。但由于一对多的关系中,关系本身在“多”方的表中。所以,无需更新
关系。
 

4. 如果cascade = "none" 且 inverse = "true"

 

Java代码 复制代码  收藏代码
  1. // 只执行对father的插入   
  2. Hibernate: insert into father (name) values (?)  
// 只执行对father的插入
Hibernate: insert into father (name) values (?)
 

可以看到,对于一对多关系,关系应由“多”方来维护(指定“一”方的inverse为true),并且应在“一”方指定相应的级联操作。

 

多对多:

 

在多对多关系中,inverse可以为任何一方,没有什么区别。

 

解疑:

 

为什么在多对多中不能由双方都来维护关系了:因为这样会导致重复更新中间表的可能,报出重复值的错误。

 

那么如何在多对多的双向关联中使双方都能维护关系:最好让控制关系的那方来更新关系,如果想让另一方也来维护关系,那么只有在操作这一方的数据时“显式”更新中间表了吧。

 

注意:

 

同时注意在双向关联中,对象之间的关联跟上面提及的关系表维护没有关系。一个是对象/java层面的,一个是hibernate数据库层面的。如果你想在更新一方时,也更新另一方的对象集合,请看下面这段代码:

 

这是Person类中的一段代码,Person和Event是多对多的双向关联关系,他们在对方类中的集合分别为participants和events。关系表由Person维护,所以对象关系的维护也在Person类中,而不是Event类中。

 

Java代码 复制代码  收藏代码
  1. public void addToEvent(Event event) {   
  2.         this.getEvents().add(event);   
  3.         event.getParticipants().add(this);   
  4. }   
  5.   
  6. public void removeFromEvent(Event event) {   
  7.         this.getEvents().remove(event);   
  8.         event.getParticipants().remove(this);   
  9. }  

这篇关于hibernate中cascade与inverse讲解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/900140

相关文章

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

java面试常见问题之Hibernate总结

1  Hibernate的检索方式 Ø  导航对象图检索(根据已经加载的对象,导航到其他对象。) Ø  OID检索(按照对象的OID来检索对象。) Ø  HQL检索(使用面向对象的HQL查询语言。) Ø  QBC检索(使用QBC(Qurey By Criteria)API来检索对象。 QBC/QBE离线/在线) Ø  本地SQL检索(使用本地数据库的SQL查询语句。) 包括Hibern

org.hibernate.hql.ast.QuerySyntaxException:is not mapped 异常总结

org.hibernate.hql.ast.QuerySyntaxException: User is not mapped [select u from User u where u.userName=:userName and u.password=:password] 上面的异常的抛出主要有几个方面:1、最容易想到的,就是你的from是实体类而不是表名,这个应该大家都知道,注意

Caused by: org.hibernate.MappingException: Could not determine type for: org.cgh.ssh.pojo.GoodsType,

MappingException:这个主要是类映射上的异常,Could not determine type for: org.cgh.ssh.pojo.GoodsType,这句话表示GoodsType这个类没有被映射到

ispunct函数讲解 <ctype.h>头文件函数

目录 1.头文件函数 2.ispunct函数使用  小心!VS2022不可直接接触,否则..!没有这个必要,方源一把抓住VS2022,顷刻 炼化! 1.头文件函数 以上函数都需要包括头文件<ctype.h> ,其中包括 ispunct 函数 #include<ctype.h> 2.ispunct函数使用 简述: ispunct函数一种判断字符是否为标点符号的函

Hibernate框架中,使用JDBC语法

/*** 调用存储过程* * @param PRONAME* @return*/public CallableStatement citePro(final String PRONAME){Session session = getCurrentSession();CallableStatement pro = session.doReturningWork(new ReturningWork<C

hibernate修改数据库已有的对象【简化操作】

陈科肇 直接上代码: /*** 更新新的数据并并未修改旧的数据* @param oldEntity 数据库存在的实体* @param newEntity 更改后的实体* @throws IllegalAccessException * @throws IllegalArgumentException */public void updateNew(T oldEntity,T newEntity

深度学习速通系列:深度学习算法讲解

深度学习算法是一系列基于人工神经网络的算法,它们通过模拟人脑处理信息的方式来学习和解决复杂问题。这些算法在图像识别、语音识别、自然语言处理、游戏等领域取得了显著的成就。以下是一些流行的深度学习算法及其基本原理: 1. 前馈神经网络(Feedforward Neural Networks, FNN) 原理:FNN 是最基本的神经网络结构,它由输入层、隐藏层和输出层组成。信息从输入层流向隐藏层,最

C#设计模式(1)——单例模式(讲解非常清楚)

一、引言 最近在学设计模式的一些内容,主要的参考书籍是《Head First 设计模式》,同时在学习过程中也查看了很多博客园中关于设计模式的一些文章的,在这里记录下我的一些学习笔记,一是为了帮助我更深入地理解设计模式,二同时可以给一些初学设计模式的朋友一些参考。首先我介绍的是设计模式中比较简单的一个模式——单例模式(因为这里只牵涉到一个类) 二、单例模式的介绍 说到单例模式,大家第一

[项目][CMP][直接向堆申请页为单位的大块内存]详细讲解

目录 1.系统调用 1.系统调用 Windows和Linux下如何直接向堆申请页为单位的大块内存: VirtualAllocbrk和mmap // 直接去堆上按页申请空间static inline void *SystemAlloc(size_t kpage){#ifdef _WIN32void *ptr = VirtualAlloc(0, kpage << 13,