最近因为工作原因,学习了尚学堂的Hibernate视频教程,于是,想自己上上手,学以致用吗。但是在自己的操作过程中遇到了一个Hibernate级联操作的问题,通过上网找资料和自己加以理解,便想记录下自己的一些想法,以备不时之用,并且可以和大家共同学习下。
马老师说在一对多关系中,最好把对级联关系的管理放在多的一方,所以我也这样做了。我设计了两个表一个user,一个advertisement,而且我在advertisement中设了cascade=CascadeType.ALL。悲剧是这样发生的:我在写好Dao的实现时,用Junit测试了一下,测试到advertisement的Delete时,悲剧反生了,我数据库中的所有数据都被删了!当然原因很快就明白了,就是级联删除惹的祸——这都是只学不想惹的祸啊。于是,困惑来临:那Hibernate的级联应该怎么设置呢?
在自己想的过程中又碰到了些概念的问题:级联删除当然比较好懂,但是什么是级联保存呢?什么是级联更新呢?(原谅我的愚昧)于是上网搜罗答案,但是基本都没讲这个的啊,郁闷,o(︶︿︶)o 唉,估计就自己比较愚昧了点了,但还是找到了些提示信息,在此将那些提示信息加上自己的理解,给它们下个粗略的形象吧:
级联保存:举个例子,就是当我产生一个advertisement时,又定义了一个新的user,于是在保存advertisement时Hibernate会将user也保存起来(如果设置了级联关系的话)。
级联更新:也举个例子,就是当我从数据库中取出advertisement时,同时也会取出user(设置了级联操作)。于是乎,在我修改的advertisement时,也可以修改user的信息,当我更新advertisement修改的信息时,Hibernate也会更新user的信息。
曾经认为更新是对主键的更新(网上也有这种说法),但是,当你的主键是自动生成的时候呢?而且很多表中主键只是避免重复,并没有修改的实际意义。所以更新主键很多情况下是不会用到的。其实纯粹从数据库的角度理解,的确级联更新应该是发生在改变了表的主键的时候,但是我想这在实际运用中应该会比较少吧(当然纯属猜测)。我想Hibernate运用中的级联更新应该我上面举的例子比较多。
在遇到问题的初期,也想过,既然放在多的一方有问题,那就把cascadeType.ALL放在一的那方应该就没问题了吧。但是通过我上面的两个概念的解释,发现,把级联更新和级联保存放在一的一方没有什么意义。同样的把级联删除放在多的一方也是有问题的。于是,便想将级联删除放一的一方,而把级联保存和级联更新放在多的一方。这样问题估计会比较完美的解决。
但是新的问题来了:好像没有cascadeType.UPDATE吧。通过上网搜的资料表明,“JPA中的CascadeType.ALL并不等于{CascadeType.PESIST,CascadeType.REMOVE,CascadeType.MERGE,CascadeType.REFRESH}。”“在Hibernate中调用session.save() or session.update()并不能触发{CascadeType.PESIST,CascadeType.REMOVE,CascadeType.MERGE,CascadeType.REFRESH}的级联操作,而能触发CascadeType.ALL的级联。”(http://sin90lzc.iteye.com/blog/1048122)。看来只有用Hibernate自己的注解或者只能用persist和merge进行相应的操作了。(这里提一个题外话,在视频里,马老师说JPA最后很可能一统天下,当时还不甚理解,现在看到这个CascadeType.ALL,若有所悟啊)
以上很多均是自己的一些想法,肯定有很多不足之处,希望各位大侠指正,在此先谢过啦。第一次写博客,有点乱,见谅。