Hibernate中inverse属性与cascade属性

Hibernate集合映射中,经常会使用到"inverse"和"cascade"这两个属性。对于我这样,Hibernate接触不深和语文水平够烂的种种因素,发现这两个属性实在是难以理解,无奈只好将这个两个属性解释工作交给了Google和Baidu,查看了许多牛人的解释,加上自己在Eclipse上的调试,对"inverse"和"cascade"这两个属性有了一定的见解。

   "inverse"属性探究

   "inverse"-直译过来就是"反转,使颠倒"的意思,书面化的解释为"是否将关系维护的权力交给对方"(这个解释真够蛋疼的-_-!!,就是理解不了)。 Hibernate中的"inverse"属性只有两个值"true"和"false"。"true"表示将关系维护的权力交给对方,"false"表示不交出维护权力(默认值)。

   例如有两张表,customer和orders,他们的关系是一对多,customer是一方,orders为多方。

    1.    drop table if exists customer;  
    1.    drop table if exists orders;  
    1.    create table customer  
    1.    (  
    1.        id varchar(255) not null,  
    1.        username varchar(255),  
    1.        password varchar(255),  
    1.        age integer,  
    1.        register_time datetime,  
    1.        primary key (id)  
    1.    );  
    1.    create table orders  
    1.    (  
    1.        id varchar(255) not null,  
    1.        orderNumber varchar(255),  
    1.        balance integer,  
    1.        customer_id varchar(255),  
    1.        primary key (id)  
    1.    ); 

   两表对应的hbm文件,对应的POJO类:

                   /*customer表对应的POJO类*/ 

                    public class Customer  

         {  

             private String id;  

             private String username;  

             private String password;  

          private Timestamp registerTime;  

                         private int age; 

           private Set<Order> orders = new HashSet<Order>();

         public Customer() {  

           }  

      1.        /*get and set method*/ 
      1.  }  

 

      1.    /*orders表对应的POJO类*/ 

 

      1.    public class Order  
      1.    {  
      1.        private String id;  
      1.        private String orderNumber;  
      1.        private int balance;  
      1.        private Customer customer;  
      1.        public Order()  
      1.        {  

 

      1.        }  
      1.        /* get and set method*/ 

 

      1.    } 

   

 

        1.    <!--Customer类的hbm文件-->  
        1.        <hibernate-mapping>  
        1.            <class name="com.suxiaolei.hibernate.pojos.Customer" table="customer">  
        1.                <id name="id" type="string">  
        1.                    <column name="id"></column>  
        1.                    <generator class="uuid"></generator>  
        1.                </id>  
        1.                <property name="username" column="username" type="string"></property>  
        1.                <property name="password" column="password" type="string"></property>  
        1.                <property name="age" column="age" type="integer"></property>  
        1.                <property name="registerTime" column="register_time" type="timestamp"></property>  

 

        1.                <set name="orders" inverse="true" cascade="all">  
        1.                    <key column="customer_id" ></key>  
        1.                    <one-to-many class="com.suxiaolei.hibernate.pojos.Order"/>  
        1.                </set>  
        1.            </class>  
        1.        </hibernate-mapping>  
        1.    <!--Order类的hbm文件-->  
        1.        <hibernate-mapping>  
        1.            <class name="com.suxiaolei.hibernate.pojos.Order" table="orders">  
        1.                <id name="id" type="string">  
        1.                    <column name="id"></column>  
        1.                    <generator class="uuid"></generator>  
        1.                </id>  
        1.                <property name="orderNumber" column="orderNumber" type="string"></property>  
        1.                <property name="balance" column="balance" type="integer"></property>  
        1.                <many-to-one name="customer" class="com.suxiaolei.hibernate.pojos.Customer">  
        1.                    <column name="customer_id"></column>  
        1.                </many-to-one>          
        1.            </class>  
          1.  </hibernate-mapping>

下面写一些测试代码测试"inverse"属性的特性:

   情况一:将"inverse"设置为true,让多方维护关系

      1.  try 
      1.    {  
      1.        tx = session.beginTransaction();  
      1.        /*  
      1.         * 创建Customer对象,并设置其属性值  
      1.         */ 
      1.        Customer customer = new Customer();  
      1.        customer.setUsername("zhangsan");  
      1.        customer.setPassword("123456");  
      1.        customer.setAge(22);  
      1.        customer.setRegisterTime(new Timestamp(new Date().getTime())); 
      1.        /*  
      1.         * 创建Order对象order1,并设置其属性值  
      1.         */ 
      1.        Order order1 = new Order();  
      1.        order1.setOrderNumber("a1a2a3");  
      1.        order1.setBalance(1000);  
      1.        order1.setCustomer(customer);//将customer对象关联到order1对象上  
      1.        /*  
      1.         * 创建Order对象order2,并设置其属性值  
      1.         */ 
      1.        Order order2 = new Order();  
      1.        order2.setOrderNumber("d3d2d1");  
      1.        order2.setBalance(670);  
      1.        order2.setCustomer(customer);///将customer对象关联到order2对象上  

              customer.getOrders().add(order1);//将order1对象关联到customer对象上  

      1.        customer.getOrders().add(order2);//将order2对象关联到customer对象上  
      1.        session.saveOrUpdate(customer);  
      1.        tx.commit();  
      1.    }   catch (Exception e)  {  
      1.        if(tx != null)  
      1.        {  
      1.            tx.rollback();  
      1.        }  
      1.        e.printStackTrace();  
      1.    }  
      1.    finally 
      1.    {  
      1.        session.close();  

   数据库中的数据更新为:

   customer表: 

   

   orders表:

   

   现在将order1.setCustomer(customer);这段代码注释掉,再次运行程序:

   customer表:

   

   orders表:

   

   可以到看到显著地差别了,第一次保存"id"="402881e534ea7c750134ea7c76bc0001"的数据时,orders表中插入了两条数据,他们的customer_id都为customer中对应记录的主键值,而第二次保存记录"id"="402881e534ea81be0134ea81bfea0001"的数据时,由于先前将原来的代码段order1.setCustomer(customer);注释掉了,此时order表中插入的数据中order1代表的那条记录没有customer_id值。

 从以上现象可以有助于理解"inverse"这个属性。首先,"inverse"控制关系维护权力,那么什么是"关系"?,关系的具体体现是什么?在以上例子中,"关系"就是两个表之间的关系,通常为"一对多","一对一","多对多"三种关系,而关系的具体体现为orders表中的 customer_id列,而"inverse"属性就是告诉Hibernate哪一方有权力管理和维护这一列。上面的例子将"inverse"设置为 true那么customer_id这一列由多方(order对象)维护。这说明了,只有order对象对关系的操作会反映到数据库中。(对象对关系的操作就是对关联属性的操作,例如order对象对自身的"customer"属性操作,customer对象对自身的orders集合(Set<Order>)操作)

   例如,将id="402881e534ea7c750134ea7c76bc0001"的customer对象从数据库中取出,获取到该customer对象所关联的order对象集合,将该customer对象所关联的order对象删除。

    1.    Customer customer = (Customer)session.get(Customer.class, "402881e534ea7c750134ea7c76bc0001");  
    1.    Order order = (Order)session.get(Order.class, "402881e534ea7c750134ea7c76ce0002");  
    1.    System.out.println("customer association order count:"+customer.getOrders().size());  
    1.    customer.getOrders().remove(order);  
    1.    System.out.println("customer association order count:"+customer.getOrders().size());  
    1.    session.saveOrUpdate(customer); 

   //Console Output:

   customer association order count:2
customer association order count:1

   可以看到customer中关联的order对象集合确实有对象被删除了,若操作有效,表示该order对象与customer对象没有关系了,反映到数据库中应该将该order对象对应的customer_id设置为null。现在查看一下数据库数据:

   

   看到了吧,刚刚那个操作就是个无用操作,不会反应到数据库中。我们修改一下程序代码:

      1.    Customer customer = (Customer)session.get(Customer.class, "402881e534ea7c750134ea7c76bc0001");  
      1.    Order order = (Order)session.get(Order.class, "402881e534ea7c750134ea7c76ce0002");  
      1.    order.setCustomer(null);  
      1.    session.saveOrUpdate(customer); 

   这次我们使用order对象来操作关系,将该order对象与customer对象脱离关系,若操作有效,则反映在数据库中应该是该order对象的customer_id字段的值变成null,现在查看一下数据库:

   

   可以看到,此次操作成功的反映到了数据库中了。

   情况二:将"inverse"属性设置为"false",双方都维护关系(因为没有一方交出权力,"inverse"的默认值为"false",而且"inverse"属性只能在set、list、map等几个标签中设置,像many-to-one这一类的标签都不能设置"inverse"这个属性值,它们只能取值"false")

   这里会产生书中所说的性能问题(囧,这个也是理解了很久很久),这个不管怎么说你都可能理解不了,我就是这样的(-_-!!),所以我建议使用第三方的软件将Hibernate输出的SQL语句的绑定值显示出来(可以参考这里)。之所以会产生性能为题,当你操作关系是会无故多产生一些update语句,比如你使用上面的例子保存一个customer对象,它关联了2个order对象,它不但会生成3条insert语句(用于插入数据),还会生成2条update语句(将关联的order对象的customer_id更新为自己的主键值),你想想要是一个customer对象包含几万了order对象(购物狂),那么每次保存它得要多生成几万条update语句,这个就是很严重的性能问题了。

   为什么Hibernate会产生update语句呢?那是Hibernate太主动,太热情,太负责的表现,它怕你出现错误,例如有几万个order对象需要关联到customer对象上,这就需要调用order.setCustomer(customer);,几万个对象这不是人可以不放错的完成的。所以Hibernate怕你出错忘记调用这个方法,所以他将会在order对象保存完毕后将所有关联对象的customer_id字段更新一遍,确保正确性,这样也就产生上面的性能问题。

   将"inverse"设置为false后,你可以尝试设置order1.setCustomer(null),它依然会正确的将customer的主键值完美的插入到order的customer_id字段上,只是会多一条update语句。

   "cascade"属性

   "cascade"-直译过来就是"级联、串联"的意思,书面化的解释为"该属性会使我们在操作主对象时,同时Hibernate帮助我们完成从属对象相应的操作(比如,有Customer和Order这两张表,关系为一对多,只使用JDBC删除Customer表中的一行记录时,我们还需要手动的将Order表中与之关联的记录全都删除,使用Hibernate的'cascade'属性后,当我们删除一条Customer记录时,Hibernate会帮助我们完成相应Order表记录的删除工作,方便了我们的工作)"。

   总 结

   使用"inverse"这个属性时,要考虑清楚关系,不然你的系统就会有大的性能问题,书本上和一些牛人建议,关系一般由"多方"维护,当遇到"多对多"时怎么办,其实多对多久是两个"一对多",随意设置一方"inverse"为"true"就可以了,不要两方都设置或都不设置(囧,我开始就是死板这样的设置)。而是用"cascade"属性时,主对象(一方)一般设置为"all",而多方不建议设置包含delete操作的选项,建议设置多方为"save-update",这是因为你删除一方,多方已经没有存在的意义了,而删除多方不能代表一方没意义了(例如,消费者和订单)。最后,"cascade"操作的是两张表的记录或两端的对象,而"inverse"操作的是两张表的关系或两个对象的关系。

转载于:https://www.cnblogs.com/suding1188/archive/2013/01/04/2844575.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/410538.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

h5 nan_h5页面在不同ios设备上的问题总结

最近在写嵌入到小程序webview的一个h5页面&#xff0c;是一个文章评论的功能&#xff0c;这个过程中&#xff0c;遇到很多兼容性的问题&#xff0c;在不同机型上的表现也很不一致&#xff0c;所以总结了以下这些问题&#xff0c;记录下来&#xff0c;以便以后查看。1、日期问题…

C# 淘宝商品微信返利助手开发-(七)返利助手开发(5)如何将优惠券地址转为淘口令

系列教程一目录&#xff1a;返利助手原理 系列教程二目录&#xff1a;返利助手开放文档以及帐号申请地址 系列教程三目录&#xff1a;返利助手开发&#xff08;1&#xff09;API介绍 系列教程四目录&#xff1a;返利助手开发&#xff08;2&#xff09;淘宝分享的内容如何只取…

ftp改为sftp_科普!一文详解 FTP、FTPS 与 SFTP 的原理

FTP、FTPS 与 SFTP 简介FTPFTP 即 文件传输协议&#xff08;英语&#xff1a;File Transfer Protocol 的缩写&#xff09;是一个用于计算机网络上在客户端和服务器之间进行文件传输的应用层协议。完整的 FTP 是由 FTP 服务器 和 FTP 客户端组成的&#xff0c;客户端可以将本地的…

动手学servlet(四) cookie和session

Cookie cookie是保存在客户端的一个“键值对”&#xff0c;用来存储用户的一些信息 cookie的应用&#xff1a; -在电子商务会话中标识用户 -对网站进行定制&#xff0c;比如你经常浏览哪些内容&#xff0c;就展示哪些页面给你 -网站广告&#xff0c;比如百度联盟&#xff0c;你…

16进制 转为图片 php_Python 十六进制hex-bytes-str之间的转换和Bcc码的生成

前言近期做测试模拟器用到了hex-bytes-str之间的转换bcc码的校验&#xff0c;这里总结了一些方法。实例直接上代码转为十六进制&#xff08;Hex&#xff09;字符串def 执行代码&#xff1a;方法&#xff1a;getStringFromNumber(size,value)参数一为生成几个batys&#xff0c;参…

推荐一个国外SaaS产品-Olark

Olark www.olark.com 是国外非常出名的一个在线客服工具。 现在国内很多人创业失败的原因是&#xff1a;什么都想自己做&#xff0c;不利用现有资源&#xff0c;结果造成做出来的东西什么都有&#xff0c;什么都不好用。 我们应该好好学习国外的小团队&#xff0c;他们只做一件…

粗暴,干就完了----徐晓冬似的C语言自学笔记-----实现一个链表结构

1 #include <stdio.h>2 #include <stdlib.h>3 #define N 54 /*N 假定数组长度为5*/5 typedef struct snode6 {7 int data;8 struct snode *next; 9 } SNODE;10 11 /*第一步&#xff0c;添加链表头信息*/12 SNODE *createhead(int a[])13 {14 SNODE *h,…

C# 淘宝商品微信返利助手开发-(二)返利助手开放文档以及帐号申请地址

系列教程一目录&#xff1a;返利助手原理 系列教程二目录&#xff1a;返利助手开放文档以及帐号申请地址 系列教程三目录&#xff1a;返利助手开发&#xff08;1&#xff09;API介绍 系列教程四目录&#xff1a;返利助手开发&#xff08;2&#xff09;淘宝分享的内容如何只取…

比较难的sql面试题,令我比较郁闷!

一组通话记录&#xff08;总共500万条&#xff09;:ID 主叫号码 被叫号码 通话起始时间 通话结束时间 通话时长1 98290000 0215466546656 2007-02-01 09:49:53.000 2007-02-01 09:50:16.000 232 98290000 021546654666 2007-02-01 09:50:29.000 2007-02-01 09:5…

阿里云ESC服务器数据快速转移至轻量应用服务器

ECS服务器的换ECS的服务器已有的数据转换就很简单了&#xff0c;直接创建自定义镜像&#xff0c;创建完成后新服务器直接更换系统盘然后选择你创建的镜像就直接吧你的数据可软件一起直接移到新的ECS的服务器了 可是坑爹的是&#xff0c;新买的轻量应用服务器里面左找右找也找…

js udp通信_nodejs源码分析第十九章 -- udp模块

udp不是面向连接的协议&#xff0c;所以使用上会比tcp简单&#xff0c;他和tcp一样&#xff0c;使用四元组来标记通信的双方&#xff08;单播的情况下&#xff09;。我们看看udp作为服务器和客户端的时候的流程。1 在c语言中使用udp1.1 服务器流程&#xff08;伪代码&#xff0…

SVN 清理失败解决方案

SVN有时因各种不明原因导致清理失败&#xff0c;可以采取如下解决办法进行处理&#xff1a; 方法一&#xff1a; 删除根目录下隐藏文件夹“.svn” 然后在根目录文件夹 外面的空白处 检出。比如你项目文件夹名为“D:/source” 则svn检出时,在“source”外面的D盘(D:/) 空白处上右…

将SQL-SERVER逆向工程导入Power-Design中并给表的字段添加注释

PD是一款不错的数据库设计工具&#xff0c;我们在项目开发的时候直接采用正向工程&#xff0c;设计好数据库后逆向将数据库导入PD中&#xff0c;并在PD中添加数据库字段的注释&#xff0c;便于新人的理解和学习&#xff0c;PD支持Oracle、SqlServer等数据库&#xff0c;是很强大…

腾讯微博Android客户端开发——自动获取验证码

上一节给大家讲解通过调用android系统自带的浏览器进行授权认证的&#xff0c;使用该种方式能很容易的完成认证&#xff0c;但是该种方式有个弊端&#xff0c;也就是如果使用第三方的浏览器如UC、天天等&#xff0c;输入完QQ账号信息点击“授权”后并不能再次跳转到MainActivit…

put请求方式参数如何传_TP5请求(request)变量

可以通过Request对象完成全局输入变量的检测、获取和安全过滤&#xff0c;支持包括$_GET、$_POST、$_REQUEST、$_SERVER、$_SESSION、$_COOKIE、$_ENV等系统变量&#xff0c;以及文件上传信息。检测变量是否设置可以使用has方法来检测一个变量参数是否设置&#xff0c;如下&…

python numpy的var std cov研究

var&#xff1a;表示方差&#xff0c; 即各项-均值的平方求和后再除以N &#xff0c; std&#xff1a;表示标准差&#xff0c;是var的平方根。 cov&#xff1a;协方差 ,与var类似&#xff0c;但是除以(N-1) import numpy as np# 构建测试数据&#xff0c;均值为10 sc [9.7, 10…

Vue手动封装实现一个五星评价得效果

我是歌谣 放弃很难 但是坚持一定很酷 微信公众号关注小歌谣 一起学习前后端知识 今天要说得是实现一个vue中实现五星评价得效果 简单来说 就是封装组件把 具体需要我们了解组件间得相互传值 数据绑定等知识 先用脚手架起个项目先 脚手架启动 ​ 安装依赖 包括 npm ins…

LetCode-MSSQL查找重复的电子邮箱

sql的题目如下所示&#xff0c;查询出重复的电子邮箱 解法(1):查询出查询出Email相等 Id不相同的数据具体语句如下所示: select a.Email from Person as a,Person as b where a.Emailb.Email and a.Id!b.Id此时我们可以看到我们的语句中输出了2次结果但是预期结果只输出了1次…

鸿蒙内核是闭源吗_鸿蒙出世,中华有为!

作者&#xff1a;飞翔吧&#xff01;橙哥转载授权(文末留言&#xff0c;或添加微信&#xff1a;mzy2117)8月9日&#xff0c;超强台风“利奇马”登陆中国。当沿海各地的人们都在琢磨下班如何回家的时候&#xff0c;在广东东莞举行的华为2019年开发者大会上&#xff0c;华为正式发…