hibernate级联删除Word文档格式.docx
《hibernate级联删除Word文档格式.docx》由会员分享,可在线阅读,更多相关《hibernate级联删除Word文档格式.docx(23页珍藏版)》请在冰豆网上搜索。
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-->
hibernate-mappingpackage="
com.scenechina.vr.model"
<
classname="
News"
table="
NEWS"
lazy="
false"
idname="
newsid"
column="
NEWSID"
type="
java.lang.Long"
generatorclass="
sequence"
paramname="
NEWS_SEQ<
/param>
/generator>
/id>
propertyname="
typeid"
TYPEID"
not-null="
true"
/>
title"
TITLE"
java.lang.String"
hitcount"
HITCOUNT"
issusedate"
ISSUSEDATE"
java.util.Date"
deployerid"
DEPLOYERID"
origin"
ORIGIN"
url"
URL"
keywords"
KEYWORDS"
priority"
PRIORITY"
special"
SPECIAL"
description"
DESCRIPTION"
author"
AUTHOR"
topic"
TOPIC"
setname="
newsset"
cascade="
all"
inverse="
order-by="
NEWSDETIALID"
Newsdetials"
keycolumn="
one-to-manyclass="
/set>
picset"
Picture"
many-to-onename="
newstype"
entity-name="
com.model.Newstype"
insert="
update="
/class>
/hibernate-mapping>
✓Newstype.hbm.xml
hibernate-mapping>
--
CreatedbytheMiddlegenHibernateplugin
http:
//boss.bekk.no/boss/middlegen/
-->
com.scenechina.vr.model.Newstype"
NEWSTYPE"
assigned"
typename"
TYPENAME"
length="
100"
dir"
DIRNAME"
templatename"
TEMPLATENAME"
--associations-->
news"
cascade="
all-delete-orphan"
inverse="
com.model.News"
其实这是个双向以对多关系。
(三)在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<
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、开发指南,级联删除就一个经典的
@Cascade({CascadeType.SAVE_UPDATE,CascadeType.DELETE_ORPHAN})
mappedBy不可少,映射A->
B一对多的另一边控制反转(谁控谁的问题),新版的Hibernate3.4中配置更简单,变一句了,更简洁吧?
orphanRemoval=true)
以上两种配置方式是等价的,下面是在实际开发中的使用了,有些时候代码方面不注意,会误以为明明配置正确了,但为什么不起作用呢?
下面例举一下代码,请看Action代码(实际上我在SpringController里,N年不写DAO了,Service很少用,Manager一边去!
CommentTeamcommentTeam=this.getHibernateTemplate.get(CommentTeam.class,id);
commentTeam.setCommentTeamMember(null);
//想级联删除子表数据
this.getHibernateTemplate.saveOrUpdate(commentTeam);
这样级联删除却没有发生?
为什么呢?
再来一个例子
Set<
commentTeamMembers=newHashSet<
();
commentTeam.setCommentTeamMember(commentTeamMembers);
//想级联删除子表数据或增减替换对象
这个例子级联删除的效果也没发生!
即使commentTeamMembers理由有若干个对象。
成功执行级联删除的语法:
commentTeam.getCommentTeamMember().clear();
//注意这里引用的集合还是原理的集合,这里没有重新new过
commentTeam.getCommentTeamMember().add(newCommentTeamMember());
//如果想替换为新的集合可以用addAll方法
分析一下原因:
级联删除起作用的前提是关联的集合对象不能重新指向新的引用,必须在原有的集合里操作新增、删除、清空元素,像上面的setXXX(null)的方法等是起步到级联删除作用的,大概是Hibernate自认自己原生的集合对象吧,自己New的放进行级联删除无效!
[java]viewplaincopy
1<
prename="
code"
class="
java"
pre>
/pre>
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<
/pr