hibernate inverse属性_iteye_3312的博客-程序员秘密

技术标签: inverse  hibernate  

inverse的含义说得玄乎点是控制翻转,说得普通就是关系的维护有谁来做。
因为在关系数据库里面table和table之间是通过外键维护关系的(1-1,1-n),对于1-n的情况,
很显然,外键由N的一方来维护比有1的一方来维护要好,这就是OOP中的has a的关系,
用hibernate进行数据存取的时候如果在集合属性里面不设置inverse=true,那么在保存n后,
hibernate会更新外键----update TEST.Groups set PARENT_ID=? where id=?(PARENT_ID
是外键)。然而这是多余的


 Hibernate一对多双向关联及inverse的作用

       在测试Hibernate的一对多双向关联映射时,碰到很有趣的问题,跟inverse属性直接相关。

1、People.hbm.xml

< hibernate-mapping   default-lazy ="false" >   
   
< class  name ="com.persistent.People"  table ="people" >      
     
< id  name ="id"  column ="peopleId"  unsaved-value ="0" >     
        
< generator  class ="increment" >         
        
</ generator >     
     
</ id >      
     
< property  name ="name"  column ="name" ></ property >      
     
< set  name ="addresses"  cascade ="save-update" >
        
< key  column ="peopleId"  not-null ="true"   />
        
< one-to-many  class ="com.persistent.Address" />
     
</ set >      
   
</ class >
</ hibernate-mapping >

2、Address.hbm.xml

< hibernate-mapping >
  
< class  name ="com.persistent.Address"  table ="address" >   
    
< id  name ="id"  column ="addressId"  unsaved-value ="0" >
        
< generator  class ="increment" >
        
</ generator >
    
</ id >     
    
< many-to-one  name ="people"  column ="peopleId"  insert ="false"  update ="false" ></ many-to-one >     
    
< property  name ="addressName"  column ="addressName" ></ property >     
    
< property  name ="codeNumber"  column ="codeNumber" ></ property >     
  
</ class >   
</ hibernate-mapping >

3、People.java和Address.java

public   class  People  {    
  
private long id;
  
private String name;
  
private Set addresses = new HashSet();
  ...
}


public   class  Address  {    
  
private long id;
  
private People people;
  
private String addressName;
  
private String codeNumber;
  ...
}
        

4、数据库结构

  people表:{peopleId,name}

  address表:{addressId,peopleId,addressName,codeNumber}

5、测试代码

People people  =   new  People();
people.setName(
"linda " );
Address address 
=   new  Address();
address.setAddressName(
"yunnan " );
address.setCodeNumber(
" 564123 " );
address.setPeople(people);
people.getAddresses().add(address);
Session session 
=  HibernateSessionFactory.getSession();
session.beginTransaction();
session.save(people);
session.getTransaction().commit();

6、运行结果

      上面测试代码运行起来正确:

Hibernate: select max(peopleId) from people
Hibernate: select max(addressId) from address
Hibernate: insert into people (name, peopleId) values (?, ?)
Hibernate: insert into address (addressName, codeNumber, peopleId, addressId) values (?, ?, ?, ?)
Hibernate: update address set peopleId=? where addressId=?

      如果将People.hbm.xml映射改写一下:

< set  name ="addresses"  cascade ="save-update"  inverse ="true" >
        
< key  column ="peopleId"  not-null ="true"   />
        
< one-to-many  class ="com.persistent.Address" />
</ set >

      不同之处在于添加了inverse="true",结果:
Hibernate: select max(peopleId) from people
Hibernate: select max(addressId) from address
Hibernate: insert into people (name, peopleId) values (?, ?)
Hibernate: insert into address (addressName, codeNumber, addressId) values (?, ?, ?)

      可以看到,peopleId并没有写入到关联的address当中,数据库address表中相应记录的peopleId字段为空。

7、分析

      在Hibernate中,术语inverse是反转的意思,在关联关系中,inverse="false"为主控方,由主控方负责维护对象的关联关系。所以上面的映射文件改动之后,address为主控方,people为被控方,但是测试代码只进行了一个保存操作session.save(people),这是针对people的,因此无法正确级联保存address。而原来的映射文件中(虽然没有明确指明,Hibernate默认inverse="false"),people为主控方,因此保存people时它会保证关联的address的正确保存。

      也就是说,Hibernate仅仅按照主控方对象的状态的变化来同步更新数据库。按照原来的映射文件,people.getAddresses().add(address),即主控方对象的状态发生了改变,因此数据库会跟着对象状态的变化来同步更新数据库;而address.setPeople(people),即被控方对象的状态发生了改变,它是不能触发对象和数据库的同步更新的。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/iteye_3312/article/details/82538763

智能推荐

应用获取Power Key/Home Key按键事件(framework层)_默默9518的博客-程序员秘密

背景有时候我们在开发的时候需要在应用中获取Power Key,Home Key等按键事件,但是我们知道这些按键属于特殊的按键,应用中并不能获取到。这些按键在framework层已经被处理掉了,因此我们需要通过一些方法来让应用能获取到。原理对于Home Key, Power key这些特殊的按键,应用是不应该获取到的,因为这些按键需要处理一些特殊的事情。应用获取到后可能会造成

Zeppelin安装(附安装包)_zeeppelin下载_习惯de味道的博客-程序员秘密

链接: https://pan.baidu.com/s/1kqdC7NrdMvxkghq8xNQN2Q提取码: qjd7版本zeppelin-0.8.1下载并解压安装包下载zeppelin移动到Linux下的opt文件夹解压:tar -zxvf zeppelin-0.8.1-bin-all.tgz重命名:mv zeppelin-0.8.1-bin-all zeppelin修改配置文件cd zeppelin/confmv zeppelin-site.xml.template zeppeli

Diffie-Hellman密钥交换_哈尔曼交换_M_Hsu的博客-程序员秘密

Diffie-Hellman 密钥交换回顾一下,前面几篇文章,首先介绍了几种经典的对称加密算法(如DES、3DES、AES和RC4),然后介绍了用于消息认证的SHA算法族,上一篇文章又开启了非对称加密算法的大门(介绍了RSA公钥加密算法)。到这里,相信大家已经对密码学中加解密的方式有了大致的了解。在这些加密算法中,我们都默认通信双方已经“安全”地掌握了加密通信时需要的密钥。那么,在加密通信开始...

微信支付V3微信公众号支付PHP教程/thinkPHP5公众号支付_tp5微信小程序支付v3_MarsWill的博客-程序员秘密

本篇文章是微信支付最新接口V3版本的PHP实践教程,在该教程中主要使用的框架是thinkPHP5框架,如果你对thinkPHP5框架下的开发还不是很熟悉可以查看相关的教程,当然在我的博客中也有thinkPHP5的教程大家可以查看。在本篇文章中我的主要目标是打更少的字让大家明白如何使用微信公众号支付。在系列教程中设计了两个非常流行的使用场景,一个场景是使用thinkPHP5实现的文章赞赏功能,一个场

重构 改善既有代码的设计(读书笔记2)_coding_or_coded的博客-程序员秘密

// 什么时候执行重构——代码的坏味道// 1.重复的代码// 2.过长的方法(当一段代码你觉得别人看起来困难,你可能需要添加注释的时候,其实你可以抽取成一个方法,然后标注一个优雅的方法名)// 3.庞大的类(很有可能职责过多,职责单一是一种很好的设计)// 4.过长的参数列表(让使用者很疲惫)// 5.发散式变化(添加一个功能,可能引起多处变化

修改ProjectConfig.mk文件后,产生编译错误_mk文件更改后_erica_sadun的博客-程序员秘密

[Description]修改ProjectConfig.mk文件后,产生编译错误 [Keyword]ProjectConfig.mk [Solution]注释符#前不存在空格且不支持条件式编译

随便推点

算法库的重要性_李迎松~的博客-程序员秘密

写软件的过程中有很多经验需要总结,其中之一就是算法库的作用和重视,一直我写软件并没有非常注意这些,只是尽量去把核心算法封装成库,但是我意识到如果将来有一天我写的软件需要升级界面,那将是一个巨大的工作量,而如果把所有功能性算法都封装成库,这个工作量就会减小很多。封装成库,对于软件的维护和升级,是非常重要的。

常见安全问题_oWindFlower的博客-程序员秘密

web安全问题常由直接和间接的输入导致直接输入:GET、POST、COOKIE、HTTP头环境变量;间接输入:数据库取出的数据、编码的用户数据1.缓冲区溢出(长字符)2.元字符(HTML3.路径遍历(../../../pass/root)4.sql注入检查(‘where 1=1’ ; http://victim/news.php?id=3721、select

高质量C编程08-预处理_chening4400的博客-程序员秘密

1.预处理的概念 C语言中,以#开头的语句统称为编译预处理命令. 这些命令必须在一行的开头以#开始,末尾不加分号,并且每条命令独占一行,以区别于一般的C语句.它们可以放在程序的任何位置. 2.宏 (1)宏是一种定义,它就是给一个语句块(宏体)定义了一个名字 #define...

Linux中断_gpio_to_irq_Vis-Lin的博客-程序员秘密

Linux驱动之中断:1、介绍了什么是中断号2、中断相关API函数3、申请和释放中断4、中断的使能和禁止5、一个简单的中断例子:按下按键触发中断,打印信息1

采用DDS设计信号发生器_weixin_30546933的博客-程序员秘密

该信号发生器采用了直接数字频率合成技术(DDS)和计算机控制技术,选择美国Analog Devices公司的高度集成DDS芯片AD9851和AT89S52单片机作为控制器件,设计了一种基于DDS的程控信号发生器。用C语言进行了软件应用设计。实验结果表明,该信号发生器能较好地产生较高稳定度的激励信号,具有较高的实用价值。1、概述 信号发生器又称信号源或振荡器,在生产实践和科技领域中有着...

推荐文章

热门文章

相关标签