举例如下

Customer类:

  1. public class Customer {
  2. private int id;
  3. private String name;
  4. private Set orders = new HashSet();
  5. •••
  6. }

即Customer类具有一个set集合属性orders,其中Order是一个普通的类:

  1. public class Order {
  2. private int id;
  3. private String orderName;
  4. •••
  5. }

数据库中表的结构:

  1. t_customer:  两个字段:id  name
  2. t_order:     三个字段:id  orderName  customerid

Customer类的映射文件:Customer.hbm.xml  (Order类的映射文件忽略)

  1. <hibernate-mapping>
  2. <class name="test.Customer" table="t_customer" lazy="false">
  3. <id name="id">
  4. <generator class="native"/>
  5. </id>
  6. <property name="name"/>
  7. <set name="orders"  cascade="save-update"  lazy="false">
  8. <key column="customerid"/>
  9. <one-to-many class="test.Order"/>
  10. </set>
  11. </class>
  12. </hibernate-mapping>

执行如下代码:

  1. Set orders = new HashSet();
  2. Order o1 = new Order();
  3. o1.setOrderName("o1");
  4. Order o2 = new Order();
  5. o2.setOrderName("o2");
  6. orders.add(o1);
  7. orders.add(o2);
  8. Customer c = new Customer();
  9. c.setName("aaa");
  10. c.setOrders(orders);
  11. session.save(c);

此时Hibernate发出的sql语句如下:

  1. Hibernate: insert into t_customer (name) values (?)
  2. Hibernate: insert into t_order (orderName) values (?)
  3. Hibernate: insert into t_order (orderName) values (?)
  4. Hibernate: update t_order set customerid=? where id=?
  5. Hibernate: update t_order set customerid=? where id=?

查看数据库:

  1. t_customer :                    t_order:
  2. id   |  name                   id   |   orderName   |   customerid
  3. 1       aaa                    1           o1              1
  4. 2           o2              1

保存Customer对象时,首先发出insert into t_customer (name) values (?)语句将c同步到数据库,由于在<set>映射中设置cascade="save-update",所以会同时保存orders集合中的Order类型的o1,o2对象(如果没有这个设置,即cascade="save-update"),那么Hibenrate不会自动保存orders集合中的对象,那么在更新时将会抛出如下异常:

  1. Hibernate: insert into t_customer (name) values (?)
  2. Hibernate: update t_order set customerid=? where id=?
  3. org.hibernate.TransientObjectException: test.Order
  4. ••••••

抛出这一异常的原因是:<set>映射默认"inverse=fasle"即由Customer对象作为主控方,那么它要负责关联的维护工作,在这里也就是负责更新t_order表中的customerid字段的值,但由于未设置cascade="save-update",所以orders集合中的对象不会在保存customer时自动保存,因此会抛出异常(如果未设置,需要手动保存)。 
现在设置cascade="save-update",同时设置inverse="true",即:

  1. •••
  2. <set name="orders" cascade="save-update" inverse="true" lazy="false">
  3. <key column="customerid"/>
  4. <one-to-many class="test.Order"/>
  5. </set>
  6. •••

同样执行上述代码,发出如下语句:

  1. Hibernate: insert into t_customer (name) values (?)
  2. Hibernate: insert into t_order (orderName) values (?)
  3. Hibernate: insert into t_order (orderName) values (?)

相比上一次执行,少了两条update语句,查看数据库:

  1. t_customer :                    t_order:
  2. id   |  name                   id   |   orderName   |   customerid
  3. 1       aaa                    1           o1              NULL
  4. 2           o2              NULL

发现t_order表中customerid的值为NULL,这是由于设置了inverse="true",它意味着 
Customer不再作为主控方,而将关联关系的维护工作交给关联对象Orders来完成。在保存Customer时,Customer不在关心Orders的customerid属性,必须由Order自己去维护,即设置order.setCustomer(customer);

如果需要通过Order来维护关联关系,那么这个关联关系转换成双向关联。 
修改Order类代码:

  1. public class Order {
  2. private int id;
  3. private String orderName;
  4. private Customer customer;
  5. •••
  6. }

Order.hbm.xml:

  1. <hibernate-mapping>
  2. <class name="test.Order" table="t_order">
  3. <id name="id">
  4. <generator class="native"/>
  5. </id>
  6. <property name="orderName"/>
  7. <many-to-one name="customer" column="customerid"/>
  8. </class>
  9. </hibernate-mapping>

此时数据库中表的结构不会变化。

再次执行上述代码,发出如下sql语句:

  1. Hibernate: insert into t_customer (name) values (?)
  2. Hibernate: insert into t_order (orderName, customerid) values (?, ?)
  3. Hibernate: insert into t_order (orderName, customerid) values (?, ?)

发现在保存Order对象时为customerid字段赋值,因为Order对象中拥有Customer属性,对应customerid字段,查看数据库表:

  1. t_customer :                    t_order:
  2. id   |  name                   id   |   orderName   |   customerid
  3. 1       aaa                    1           o1              NULL
  4. 2           o2              NULL

发现customerid的值仍为NULL,因为在上述代码中并未设置Order对象的Customer属性值,由于设置了inverse="true",所以Order对象需要维护关联关系,所以必须进行设置,即 
order.setCustomer(customer);

修改上述代码为:

  1. •••
  2. Customer c = new Customer();
  3. Set orders = new HashSet();
  4. Order o1 = new Order();
  5. o1.setOrderName("o1");
  6. o1.setCustomer(c);
  7. Order o2 = new Order();
  8. o2.setOrderName("o2");
  9. o2.setCustomer(c);
  10. orders.add(o1);
  11. orders.add(o2);
  12. c.setName("aaa");
  13. c.setOrders(orders);
  14. session.save(c);
  15. •••

执行上述代码,发出如下语句:

  1. Hibernate: insert into t_customer (name) values (?)
  2. Hibernate: insert into t_order (orderName, customerid) values (?, ?)
  3. Hibernate: insert into t_order (orderName, customerid) values (?, ?)

查看数据库:

  1. t_customer :                    t_order:
  2. id   |  name                   id   |   orderName   |   customerid
  3. 1       aaa                    1           o1              1
  4. 2           o2              1

发现已经设置了customerid的值。

在一对多关联中,在一的一方设置inverse="true"(即由多来维护!!),有助于性能的改善。通过上述分析可以发现少了update语句。

hibernate 一对多,由谁维护性能最优的更多相关文章

  1. hibernate 一对多双向关联 详解

    一.解析: 1.  一对多双向关联也就是说,在加载班级时,能够知道这个班级所有的学生. 同时,在加载学生时,也能够知道这个学生所在的班级. 2.我们知道,一对多关联映射和多对一关联映射是一样的,都是在 ...

  2. Hibernate一对多OnetoMany

    ------------------------Hibernate一对多OnetoMany 要点: 配置在一端. 1.如果是单向关联,即只在一端配置OneToMany,多端不配置ManyToOne.则 ...

  3. Hibernate一对多单向关联和双向关联映射方法及其优缺点 (待续)

    一对多关联映射和多对一关联映射实现的基本原理都是一样的,既是在多的一端加入一个外键指向一的一端外键,而主要的区别就是维护端不同.它们的区别在于维护的关系不同: 一对多关联映射是指在加载一的一端数据的同 ...

  4. Hibernate一对多操作

    --------------------siwuxie095 Hibernate 一对多操作 以客户和联系人为例,客户是一,联系人是多 即 一个客户里面有多个联系人,一个联系人只能属于一个客户 注意: ...

  5. Hibernate一对多自关联、多对多关联

    今天分享hibernate框架的两个关联关系    多对多关系注意事项 一定要定义一个主控方 多对多删除 主控方直接删除 被控方先通过主控方解除多对多关系,再删除被控方 禁用级联删除 关联关系编辑,不 ...

  6. Java进阶知识10 Hibernate一对多_多对一双向关联(Annotation+XML实现)

    本文知识点(目录): 1.Annotation 注解版(只是测试建表)    2.XML版 的实现(只是测试建表)    3.附录(Annotation 注解版CRUD操作)[注解版有个问题:插入值时 ...

  7. hibernate一对多关联映射

    一对多关联映射 映射原理 一对多关联映射和多对一关联映射的映射原理是一致的,都是在多的一端加入一个外键,指向一的一端.关联关系都是由多端维护,只是在写映射时发生了变化. 多对一和一对多的区别 多对一和 ...

  8. Hibernate一对多配置

    刚刚学习了Hibernate框架的基础知识,下面我来说说关于Hibernate一对多的配置 首先是大配置 连接数据库 用户名 和密码 能和小配置连接 部门小配置: 员工小配置: 部门实体类 员工实体类 ...

  9. Spring / Hibernate 应用性能调优

    来源:ImportNew - 陈晓舜 对大部分典型的Spring/Hibernate企业应用来说,应用的性能大部分由持久层的性能决定. 这篇文章会重温一下怎么去确认我们的应用是否是”数据库依赖(dat ...

随机推荐

  1. scikit Flow ,tensor flow 做ml模型

    [https://github.com/ilblackdragon/tf_examples/blob/master/titanic.py] [keras 高层tensorflow] https://k ...

  2. CNN、RNN、DNN

    一:神经网络 技术起源于上世纪五.六十年代,当时叫感知机(perceptron),包含有输入层.输出层和一个隐藏层.输入的特征向量通过隐藏层变换到达输出层,由输出层得到分类结果.但早期的单层感知机存在 ...

  3. 6-Qt给父widget加上styleSheet(添加背景图)而不改变子widget的styleSheet的方法

    Qt给父widget加上styleSheet(添加背景图)而不改变子widget的styleSheet的方法 比如用stylesheet给widget加背景图,可以用qt designer修改ui文件 ...

  4. Linux CentOS6.6 NFS服务的配置与安装

    一.简介 NFS(Network File System)即网络文件系统,是FreeBSD支持的文件系统中的一种,它允许网络中的计算机之间通过TCP/IP网络共享资源.在NFS的应用中,本地NFS的客 ...

  5. ThinkPHP5路由图解

  6. BZOJ 1430 小猴打架 - prufer数列

    描述 一开始森林里面有N只互不相识的小猴子,它们经常打架,但打架的双方都必须不是好朋友.每次打完架后,打架的双方以及它们的好朋友就会互相认识,成为好朋友.经过$N-1$次打架之后,整个森林的小猴都会成 ...

  7. [Selenium]Eclipse hangs at 57% in debug mode with TestNG tests

    案例1: I am very thankful to saish and cbeust for the solution. I went through the similar issue with ...

  8. Hadoop 系列(一)基本概念

    Hadoop 系列(一)基本概念 一.Hadoop 简介 Hadoop 是一个由 Apache 基金会所开发的分布式系统基础架构,它可以使用户在不了解分布式底层细节的情況下开发分布式程序,充分利用集群 ...

  9. 关闭文件描述符-close

    头文件:#include<unistd.h> 原型:int close(int fd); 返回值:成功返回0,失败返回-1.

  10. 【JS】 伪主动触发input:file的click事件

    大家用到input:file标签时,对于input:file的样式难看的处理方法一般有2种: 采用透明化input:file标签的方法,上面放的input:file标签,下面放的是其他标签,实际点击的 ...