hibernate级联删除.docx
- 文档编号:8005668
- 上传时间:2023-01-27
- 格式:DOCX
- 页数:23
- 大小:45.77KB
hibernate级联删除.docx
《hibernate级联删除.docx》由会员分享,可在线阅读,更多相关《hibernate级联删除.docx(23页珍藏版)》请在冰豆网上搜索。
hibernate级联删除
JPA下的Hibernate实现一对多级联删除5
Hibernate级联问题9
级联问题:
11
hibernate级联删除问题之inverse配置13
hibernate级联删除15
Hibernate实现级联删除
(一)
我的使用背景:
v有新闻和新闻类型,一条新闻只能属于一个类型,一种新闻类型可以对应多条新闻。
v在数据库中,新闻受新闻类型外键约束,并可以级联删除
v在Hibernate中,实现级联删除
(一)创建数据库表和关系
DROPTABLENewsType;
CREATETABLENewsType
(
TypeIDNUMBER(10)PRIMARYKEYNOTNULL,
TypeNameVARCHAR2(400)NOTNULL,
DirNameVARCHAR2(400)NOTNULL,
TemplateNameVARCHAR2(400)NOTNULL
);
DROPSEQUENCENEWSTYPE_SEQ;
CREATESEQUENCENEWSTYPE_SEQINCREMENTBY1STARTWITH1;
DROPTABLENews;
CREATETABLENews
(
NewsIDNUMBER(10)PRIMARYKEYNOTNULL,
TypeIDNUMBER(10)NOTNULL,
TitleVARCHAR2(400)NOTNULL,
HitCountNUMBER(10)DEFAULT0NOTNULL,
IssuseDateDATENOTNULL,
DeployerIDNUMBER(10)NOTNULL,
OriginVARCHAR2(400)NOTNULL,
URLVARCHAR2(400)NOTNULL,
KEYWORDSVARCHAR(400),
PriorityNUMBER(10)DEFAULT0NOTNULL,
SpecialVARCHAR2(400),
DescriptionVARCHAR2(400),
AuthorVARCHAR2(400),
TopicVARCHAR2(400)
);
DROPSEQUENCENEWS_SEQ;
CREATESEQUENCENEWS_SEQINCREMENTBY1STARTWITH1;
在oralce中,设置数据表的约束关系如下图:
(二)实现数据表到POJO的映射
映射类,我们略去,此处主要显示配置文件
✓News.hbm.xml
xmlversion="1.0"encoding="UTF-8"?
>
DOCTYPEhibernate-mappingPUBLIC"-//Hibernate/HibernateMappingDTD3.0//EN"
"
--DONOTEDIT:
Thisisageneratedfilethatissynchronized-->
--byMyEclipseHibernatetoolintegration.-->
--CreatedFriNov1121:
59:
47CST2005-->
✓Newstype.hbm.xml
xmlversion="1.0"?
>
DOCTYPEhibernate-mappingPUBLIC"-//Hibernate/HibernateMappingDTD3.0//EN"
"
--
CreatedbytheMiddlegenHibernateplugin
http:
//boss.bekk.no/boss/middlegen/
-->
--associations-->
其实这是个双向以对多关系。
(三)在DAO中实现级联删除
//删除新闻类型记录
dao.getNewsTypeDAO().deleteObjects(typeIDs);
typeID是新闻类型的主键
执行此操作将会删除所有此新闻类型的新闻。
news是一个Set类型的变量,用来存放此类型的所有的新闻。
(四)删除时遇到的问题
在数据库中,如果设置了约束关系,那么一定要允许级联删除,否则,你在执行删除时会抛出异常。
如果我们的数据库关系设置如下:
画圈的那个选项没有选上的话,那么我们在执行的时候就会抛出如下的异常:
006-04-0613:
20:
16ERROR[http-8080-Processor23](JDBCExceptionReporter.java:
72
-ORA-02292:
违反完整约束条件(SC.NEWS_TYPE_RELATIONS)-已找到子记录日志
rg.hibernate.exception.ConstraintViolationException:
couldnotexecuteupdateq
ery
atorg.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.j
va:
69)
atorg.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelp
r.java:
43)
atorg.hibernate.hql.ast.exec.BasicExecutor.execute(BasicExecutor.java:
8
)
问题的关键在如下两点:
1.数据库中要允许数据表的级联删除
2.在映射文件中要将级联删除配置正确
JPA下的Hibernate实现一对多级联删除
再谈Hibernate级联删除——JPA下的Hibernate实现一对多级联删除CascadeType.DELETE_ORPHAN
声明:
1、本文系原创,非抄袭或转载过来的。
2、本文论点都亲手做过实验论证。
3、本文所讲的Hibernate配置都基于注解的方式,hbm语法未提供。
很多人对持久层概念搞不清JPA、Hibernate、EJB3.0的关系,这里做一下简单的说明:
JPA是一个持久层设计接口,EJB3.0和Hibernate是具体的实现类,EJB3.0和Hibernate的功能近似相等的(Hibernate没有SessionBean,SpringMVC3的SessionAttribute跟SessionBean近似)。
理论是使用JPA接口可以无缝切换持久层实现,但是仅仅是理论上!
!
!
JPA是在Hibernate成熟并大行其道的时候才推出的,基本上是借鉴Hibernate的优点,做了一个统一的标准而已,JPA1.0没有一对多的级联删除配置,也许JPA2.0里才有吧(这里没做过调研)
@OneToMany(mappedBy="commentTeam")
@Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE,org.hibernate.annotations.CascadeType.DELETE_ORPHAN})
privateSet
这里为了说明,只贴出一对多的关键代码,其它无关的注解已忽略掉,以免造成干扰。
这里重点说明一下四个常用的注解配置的区别:
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})
privateSet
mappedBy不可少,映射A->B一对多的另一边控制反转(谁控谁的问题),新版的Hibernate3.4中配置更简单,变一句了,更简洁吧?
@OneToMany(mappedBy="commentTeam",orphanRemoval=true)
privateSet
以上两种配置方式是等价的,下面是在实际开发中的使用了,有些时候代码方面不注意,会误以为明明配置正确了,但为什么不起作用呢?
下面例举一下代码,请看Action代码(实际上我在SpringController里,N年不写DAO了,Service很少用,Manager一边去!
)
CommentTeamcommentTeam=this.getHibernateTemplate.get(CommentTeam.class,id);
commentTeam.setCommentTeamMember(null);//想级联删除子表数据
this.getHibernateTemplate.saveOrUpdate(commentTeam);
这样级联删除却没有发生?
为什么呢?
再来一个例子
CommentTeamcommentTeam=this.getHibernateTemplate.get(CommentTeam.class,id);
Set
commentTeam.setCommentTeamMember(commentTeamMembers);//想级联删除子表数据或增减替换对象
this.getHibernateTemplate.saveOrUpdate(commentTeam);
这个例子级联删除的效果也没发生!
即使commentTeamMembers理由有若干个对象。
成功执行级联删除的语法:
CommentTeamcommentTeam=this.getHibernateTemplate.get(CommentTeam.class,id);
commentTeam.getCommentTeamMember().clear();//注意这里引用的集合还是原理的集合,这里没有重新new过
commentTeam.getCommentTeamMember().add(newCommentTeamMember());//如果想替换为新的集合可以用addAll方法
this.getHibernateTemplate.saveOrUpdate(commentTeam);
分析一下原因:
级联删除起作用的前提是关联的集合对象不能重新指向新的引用,必须在原有的集合里操作新增、删除、清空元素,像上面的setXXX(null)的方法等是起步到级联删除作用的,大概是Hibernate自认自己原生的集合对象吧,自己New的放进行级联删除无效!
[java]viewplaincopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- hibernate 级联 删除