再谈Hibernate级联删除——JPA下的Hibernate实现一对多级联删除CascadeType.DELETE_ORPHAN

声明:

1、本文系原创,非抄袭或转载过来的。

2、本文论点都亲手做过实验论证。

3、本文所讲的Hibernate配置都基于注解的方式,hbm语法未提供。

非常多人对持久层概念搞不清JPA、Hibernate、EJB3.0的关系,这里做一下简单的说明:JPA是一个持久层设计接口,EJB3.0和Hibernate是详细的实现类,EJB3.0和Hibernate的功能近似相等的(Hibernate没有Session Bean,Spring MVC3的SessionAttribute跟Session Bean近似)。

理论是使用JPA接口能够无缝切换持久层实现,可是不过理论上!!!

JPA是在Hibernate成熟并大行其道的时候才推出的,基本上是借鉴Hibernate的长处,做了一个统一的标准而已,JPA1.0没有一对多的级联删除配置,或许JPA2.0里才有吧(这里没做过调研)

@OneToMany(mappedBy = "commentTeam")

@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE,org.hibernate.annotations.CascadeType.DELETE_ORPHAN})

private Set<CommentTeamMember> commentTeamMembers;

这里为了说明,仅仅贴出一对多的关键代码,其他无关的注解已忽略掉,以免造成干扰。

这里重点说明一下四个经常使用的注解配置的差别:

CascadeType.SAVE_UPDATE

CascadeType.ALL

CascadeType.DELETE

CascadeType.DELETE_ORPHAN

之全部之列出这四个,是由于我不想跟书本上把全部的概念都罗列出来。基本上开发时当中的3个都以及足够用了,以下我结合代码演示一下他们之间的差别,以及使用的时候注意的地方。

CascadeType.SAVE_UPDATE:Hibernate专有的,JPA并不支持,作用是级联保存、级联更新(注:JPA非常恶心,要么你配置

CascadeType.ALL,要么你配CascadeType.SAVE+CasadeType.Merge。八卦一句:专家虽牛,多年不写代码,定的标准让编码麻烦呀!)

CascadeType.ALL:级联保存、改动、删除、同步,一般非常少用,看看控制台的一长串SQL就知道性能低下,你没改的关联表也给你发update语句,我从来没用过这个属性。

CascadeType.DELETE:当调用session.delete(A)的时候,级联删除关联的对象。(注:先调用A.setB(null),再调用session.delete(A),这样是级联删不掉B的。

CascadeType.DELETE_ORPHAN:一对多级联删除。

以下重点来说说这个CascadeType.DELETE_ORPHAN:

看过API、开发指南,级联删除就一个经典的

@OneToMany(mappedBy = "commentTeam")

@Cascade({CascadeType.SAVE_UPDATE,CascadeType.DELETE_ORPHAN})

private Set<CommentTeamMember> commentTeamMembers;

mappedBy不可少,映射A->B一对多的还有一边控制反转(谁控谁的问题),新版的Hibernate3.4中配置更简单,变一句了,更简洁吧?

@OneToMany(mappedBy = "commentTeam",orphanRemoval=true)

private Set<CommentTeamMember> commentTeamMembers;

以上两种配置方式是等价的,以下是在实际开发中的使用了,有些时候代码方面不注意,会误以为明明配置正确了,但为什么不起作用呢? 以下例举一下代码,请看Action代码(实际上我在Spring Controller里,N年不写DAO了,Service非常少用,Manager一边去!)

CommentTeam commentTeam=this.getHibernateTemplate.get(CommentTeam.class,id);

commentTeam.setCommentTeamMember(null);//想级联删除子表数据

this.getHibernateTemplate.saveOrUpdate(commentTeam);

这样级联删除却没有发生?为什么呢?

再来一个样例

CommentTeam commentTeam=this.getHibernateTemplate.get(CommentTeam.class,id);

Set<CommentTeamMember> commentTeamMembers=new HashSet<CommentTeamMember>();

commentTeam.setCommentTeamMember(commentTeamMembers);//想级联删除子表数据或增减替换对象

this.getHibernateTemplate.saveOrUpdate(commentTeam);

这个样例级联删除的效果也没发生!即使commentTeamMembers理由有若干个对象。

成功运行级联删除的语法:

CommentTeam commentTeam=this.getHibernateTemplate.get(CommentTeam.class,id);

commentTeam.getCommentTeamMember().clear();//注意这里引用的集合还是原理的集合,这里没有又一次new过

commentTeam.getCommentTeamMember().add(new CommentTeamMember());//假设想替换为新的集合能够用addAll方法

this.getHibernateTemplate.saveOrUpdate(commentTeam);

分析一下原因:级联删除起作用的前提是关联的集合对象不能又一次指向新的引用,必须在原有的集合里操作新增、删除、清空元素,像上面的setXXX(null)的方法等是起步到级联删除作用的,大概是Hibernate自认自己原生的集合对象吧,自己New的放进行级联删除无效!
































































































				
时间: 2024-10-18 16:52:43

再谈Hibernate级联删除——JPA下的Hibernate实现一对多级联删除CascadeType.DELETE_ORPHAN的相关文章

【JPA 级联保存/级联删除】@OneToMany (双向) 一对多【转】

[http://blog.sina.com.cn/s/blog_625d79410101dbdd.html] 看过前两篇帮助文档 [JPA] @OneToOne 单向 和 [JPA]@OneToOne 双向 想必大家对级联操作已经充满了好奇和期待吧.那么本文将会想大家介绍JPA的级联保存操作.在此之前,我希望你能先看下这篇文档,对级联注释的各个属性有一个大概的了解.传送门:[JPA] 级联标签的解释 @Cascade 在生活中,有许多关系都是一对多的.School(学校)和 Studnet(学生

再谈multistage text input(中文输入法)下UITextView的内容长度限制

之前写过一篇<如何更好地限制一个UITextField的输入长度>,在文章最后得到的结论是可以直接使用 UIKIT_EXTERN NSString *const UITextFieldTextDidChangeNotification; 进行监听,截断超出maxLength的部分. 所以后来我在处理UITextView的内容长度时,也直接参考这个方法: [[NSNotificationCenter defaultCenter] addObserver:self selector:@select

C++ Primer 学习笔记_44_STL实践与分析(18)--再谈迭代器【下】

STL实践与分析 --再谈迭代器[下] 三.反向迭代器[续:习题] //P355 习题11.19 int main() { vector<int> iVec; for (vector<int>::size_type index = 0; index != 10; ++index) { iVec.push_back(index); } for (vector<int>::reverse_iterator r_iter = iVec.rbegin(); r_iter !=

再谈删除数据的SQL语句

无论是刚毕业的大学生还是已经在软件领域拼杀多年的老手,只要提及删除数据的SQL语句无人不知无人不晓,再谈删除数据的SQL语句不免显得卖弄,呵呵呵,不要好高骛远: 有如下两个表: 表1: CREATE TABLE `lm_r_user_info` ( `id` CHAR(36) NOT NULL COMMENT '用户基础信息ID', `real_name` VARCHAR(30) NOT NULL COMMENT '真实姓名', `gender` INT(11) DEFAULT NULL COM

JPA中自定义的插入、更新、删除方法为什么要添加@Modifying注解和@Transactional注解?

前几天,有个同事在使用JPA的自定义SQL方法时,程序一直报异常,捣鼓了半天也没能解决,咨询我的时候,我看了一眼他的程序,差不多是这个样子的: 1 @Repository 2 public interface UserRepository extends JpaRepository<User,Long> { 3 4 @Query(value = "delete from pro_user where id = ?1",nativeQuery = true) 5 void d

eclipse从数据库逆向生成Hibernate实体类(eclipse中反向生成hibernate实体类+jpa注释)

eclipse从数据库逆向生成Hibernate实体类 做项目必然要先进行数据库表设计,然后根据数据库设计建立实体类(VO),这是理所当然的,但是到公司里做项目后,让我认识到,没有说既进行完数据库设计后还要再"自己"建立一变VO.意思是,在项目设计时,要么根据需求分析建立实体类,由正向生成数据库表:要么就先进行数据库表设计,再逆向生成实体类.没有说进行完任意一方的设计后再去花时间去自己匹配建立另一方的设计. 原因是: 1. 1.5倍工作量,浪费时间.(时间对公司来说很重要) 2. 无法

Another Look at Events(再谈Events)

转载:http://www.qtcn.org/bbs/simple/?t31383.html Another Look at Events(再谈Events) 最近在学习Qt事件处理的时候发现一篇很不错的文章,是2004年季刊的一篇文章,网上有这篇文章的翻译版,但是感觉部分地方翻译的比较粗糙,不是很明确.索性重新翻译了一遍,并引用了原翻译版的一段译注.以下都是用自己能理解的方式来翻译的,由于水平有限,有很多不足的地方,希望大家指正. Another Look at Events (再谈Event

XML方式下的Hibernate的配置问题

废话不多说,直接先来看一波代码: 实体类: com.hbm.entity包下的Log实体类(Log.java): package com.hbm.entity; import java.io.Serializable;import java.util.Date;/**日志实体类**/public class Log implements Serializable{        private static final long serialVersionUID = 28237173392831

再谈word2003编程

再谈word2003编程 近期因为项目需要,写了许多word2003编程的东东.有时候遇到难题想查sdk说明,很难找到中文解释,对于e文不好的我来说,简直是天书.想必很多人多有感慨.     下面列出内容是一些常用的内容说明,希望对大家有帮助.     那就开始吧注意,下文的WAPP是我定义的word文档工程变量 的 //合并单元格    table.Cell(2, 2).Merge(table.Cell(2, 3));  //单元格分离     object Rownum = 2;     o