Hibernate关于inverse与cascade属性的一些理解

cascade很好理解,就是对表进行增,删,改(查询与它无关)的时候对级联表进行操作,简单的来就是session.save(),session.delete()或者sesison.update()对一个表进行操作时,也会跟它有外键的表产生影响


cascade属性的可选值:

all :所有情况下均进行关联操作。

none:所有情况下均不进行关联操作。这是默认值。

save-update:在执行save/update/saveOrUpdate时进行关联操作。

delete:在执行delete时进行关联操作。


inverse

网上关于inverse的理解大都是决定主表还是从表维护关系但这实在有点抽象,经过进行实验观察sql语句终于有了一些理解。


inverse有两种属性:

falsetrue;理解就一句话,谁设置了谁就要维护表的关系。举一个例子:对于<one-to-many>的双向关联情况,<one-to-many inverse="true"/>代表主控权不在"一"端这方,而在“多”端的那一方,反之则是主控权在“多”端那一方。


下面通过举例子来探究主控权在哪一方会出现什么不同

这里先给出结论:主控权在哪里所影响的sql语句的不同,从而影响了结果。本文的重点就是探究怎么影响结果!

实验环境: <one-to-many>一对多的双向关系(也可以看成是多对一的双向关系)

表: user:

group表:

其中,group的id字段作为user表的groupid的外键


增加的情况下

<span style="white-space:pre">	</span><pre name="code" class="java"><pre name="code" class="java"><span style="font-size:18px;">		User user1 = new User();
		User user2 = new User();
		Group group = new Group();
		Session session = sessionfactory.openSession();
		session.beginTransaction();
		
		user1.setName("刘备");
		user2.setName("关羽");
		group.setName("蜀国");
		
		group.getUsers().add(user1);
		group.getUsers().add(user2);
		session.save(group);</span>


 

 

下面的inverse与cascade属性均是在Group.hbm.xml下设置。User.hbm.xml下的inverse均为true,cascade属性均为all

1.inverse=truecascade=none

执行的sql语句如下:


解释如下:cascade设为none,对group的操作不影响user。所以只有一句insert插入语句。inverse为true,主控权在user这里,由于是第一个例子暂时看不出inverse的作用。

2.inverse=true,cascade=all

执行的sql语句如下:


解释如下:cascade为all,对group的操作影响user表,但是user表中的groupid为空。可以肯定的是groupid为空是inverse=true;的影响。

再看下面的这种情况:

3.inverse=false,cascade=all

执行的语句如下:

  •  

结果是保存group的数据时也把user的数据给保存了,并且groupid也添加上了。下面观察下sql语句,

对比上一种情况下的sql语句明显多出来了两句update。看到这里,相信你一定想到是为什么了。没错,就是inverse=false带来的影响!!!

inverse=false代表主控权在group上,主控权的作用是什么?就是维护两张表的关系(也可以简单理解为外键关系)!好了这是我们按照人的思维上的理解,试着站着机器的角度上看,cascade=all已经把group的全部值与user中除了groupid的值正常保存进去了,现在inverse也设为false,那你要我group来维护这两张的关系那肯定是通过update来把user表中的groupid由null设为group表中的id值了!

看到这里大家肯定会存在一个疑问,那对于上一种情况下,即inverse=true,与cascade=all的情况下,user不也是掌控这主控权么?那怎么groupid保存不了呢?这是问题的核心,不知道大家有没有观察到另一个关键之处,那就是session.save()存储的是group!而不是user!存储的是group,即使你的主控权是user那也没产生任何影响,Hibernate只会单纯的存储数据,而不会帮你维护关系。


大家再来思考一下,加上user1.setGroups(group)与user2.setGroups(group),并且inverse=true,cascade=all时,会发生什么事情,你会惊奇的发现groupid加上去了!BTW,在这里groupid加上去只是use.setGroups()的作用,并不是update语句的影响,执行的sql语句如下:



相信大家看到这里已经对inverse理解的已经有点感觉了。再来看看下面这种情况;

4.inverse=false,cascade=none

这里大家猜会怎样?答案是会发生异常,原因很简单:inverse=false,这时主控权在group,session.save()存储的又是group,那么Hibernate肯定会发出update语句来维护关系,但是你cascade=none,所带来的影响的是不能影响user表,那么user表中的对象为空,你update语句是需要id的,那你id为空update肯定不能执行,从而产生异常。



有了上面对于增加情况的分析,那么下面的删除情况就会很容易理解了。

删除的情况下

<span style="font-size:14px; white-space: pre;">		</span><span style="font-size:18px;">Session s = sessionfactory.openSession();</span><span style="font-size:14px;">
</span><span style="font-size:14px; white-space: pre;">		</span><span style="font-size:18px;">s.beginTransaction();
<span style="white-space: pre;">	</span>     Group g = (Group)s.get(Group.class, 1);
<span style="white-space: pre;">	</span>     s.delete(g);
<span style="white-space: pre;">	</span>     s.getTransaction().commit();
             s.close();</span>


下面的inverse与cascade属性均是在Group.hbm.xml下设置。User.hbm.xml下的inverse均为true,cascade属性均为all

1.inverse=false, cascade=none

执行的sql语句如下:


结果是group全部删除,user表groupid设为空,其它数据不变.

解释如下:主控权为group,Hibernate删除时会为了维护两张表的外键关系而发出update语句,从而groupid为空。cascade=none,从而没有删除user的除了外键groupid之外的其它数据。

2.inverse=false,cascade=all

执行的sql语句如下:


执行的结果如下:group与user表内容全部删除!

解释如下:inverse=false,Hibernate在删除group的时候会为了维护外键而产生update语句,把user表的groupid字段设置为null。

cascade=all,则Hibernate会在删除group时会根据id产生delete语句把user表数据整条删除掉,从而group与user表全部删除。


3.inverse=true,cascade=none

结果很明显出现异常,出现的原因为:user的外键约束。

解释为:inverse=true,group表不维护外键,那么就不会产生updage语句。cascade=none,删除group不会把根据id把user整条数据删除。那么Hibernate执行sql语句是肯定会出现外键约束异常,Hibernate的最底部还是要通过sql语句来操作语句的,没有什么特殊的。


4.inverse=true,cascade=all

执行sql语句如下:


执行的结果为:group表与user表全部删除。

解释为:inverse=true,主控权在user表那里,所以不执行update语句。cascade=all,那么删除group时会根据id产生delete语句把user表中的整条语句删除掉。从而user表也为空。


修改的情况下

其实修改完全可以看成增加的一种的特殊情况,只不过把insert换成update语句而已,其它基本不变。在这里就不过多阐述了。



粗暴的小总结一下:1. inverse影响的是外键靠谁维护(可以看成执行update语句)。

      2.inverse与cascade没有直接关系。

      




欢迎指出文章的不足和错误之处!



  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值