hibernate 一对多,由谁维护性能最优
举例如下
Customer类:
- public class Customer {
- private int id;
- private String name;
- private Set orders = new HashSet();
- •••
- }
即Customer类具有一个set集合属性orders,其中Order是一个普通的类:
- public class Order {
- private int id;
- private String orderName;
- •••
- }
数据库中表的结构:
- t_customer: 两个字段:id name
- t_order: 三个字段:id orderName customerid
Customer类的映射文件:Customer.hbm.xml (Order类的映射文件忽略)
- <hibernate-mapping>
- <class name="test.Customer" table="t_customer" lazy="false">
- <id name="id">
- <generator class="native"/>
- </id>
- <property name="name"/>
- <set name="orders" cascade="save-update" lazy="false">
- <key column="customerid"/>
- <one-to-many class="test.Order"/>
- </set>
- </class>
- </hibernate-mapping>
执行如下代码:
- Set orders = new HashSet();
- Order o1 = new Order();
- o1.setOrderName("o1");
- Order o2 = new Order();
- o2.setOrderName("o2");
- orders.add(o1);
- orders.add(o2);
- Customer c = new Customer();
- c.setName("aaa");
- c.setOrders(orders);
- session.save(c);
此时Hibernate发出的sql语句如下:
- Hibernate: insert into t_customer (name) values (?)
- Hibernate: insert into t_order (orderName) values (?)
- Hibernate: insert into t_order (orderName) values (?)
- Hibernate: update t_order set customerid=? where id=?
- Hibernate: update t_order set customerid=? where id=?
查看数据库:
- t_customer : t_order:
- id | name id | orderName | customerid
- 1 aaa 1 o1 1
- 2 o2 1
保存Customer对象时,首先发出insert into t_customer (name) values (?)语句将c同步到数据库,由于在<set>映射中设置cascade="save-update",所以会同时保存orders集合中的Order类型的o1,o2对象(如果没有这个设置,即cascade="save-update"),那么Hibenrate不会自动保存orders集合中的对象,那么在更新时将会抛出如下异常:
- Hibernate: insert into t_customer (name) values (?)
- Hibernate: update t_order set customerid=? where id=?
- org.hibernate.TransientObjectException: test.Order
- ••••••
抛出这一异常的原因是:<set>映射默认"inverse=fasle"即由Customer对象作为主控方,那么它要负责关联的维护工作,在这里也就是负责更新t_order表中的customerid字段的值,但由于未设置cascade="save-update",所以orders集合中的对象不会在保存customer时自动保存,因此会抛出异常(如果未设置,需要手动保存)。
现在设置cascade="save-update",同时设置inverse="true",即:
- •••
- <set name="orders" cascade="save-update" inverse="true" lazy="false">
- <key column="customerid"/>
- <one-to-many class="test.Order"/>
- </set>
- •••
同样执行上述代码,发出如下语句:
- Hibernate: insert into t_customer (name) values (?)
- Hibernate: insert into t_order (orderName) values (?)
- Hibernate: insert into t_order (orderName) values (?)
相比上一次执行,少了两条update语句,查看数据库:
- t_customer : t_order:
- id | name id | orderName | customerid
- 1 aaa 1 o1 NULL
- 2 o2 NULL
发现t_order表中customerid的值为NULL,这是由于设置了inverse="true",它意味着
Customer不再作为主控方,而将关联关系的维护工作交给关联对象Orders来完成。在保存Customer时,Customer不在关心Orders的customerid属性,必须由Order自己去维护,即设置order.setCustomer(customer);
如果需要通过Order来维护关联关系,那么这个关联关系转换成双向关联。
修改Order类代码:
- public class Order {
- private int id;
- private String orderName;
- private Customer customer;
- •••
- }
Order.hbm.xml:
- <hibernate-mapping>
- <class name="test.Order" table="t_order">
- <id name="id">
- <generator class="native"/>
- </id>
- <property name="orderName"/>
- <many-to-one name="customer" column="customerid"/>
- </class>
- </hibernate-mapping>
此时数据库中表的结构不会变化。
再次执行上述代码,发出如下sql语句:
- Hibernate: insert into t_customer (name) values (?)
- Hibernate: insert into t_order (orderName, customerid) values (?, ?)
- Hibernate: insert into t_order (orderName, customerid) values (?, ?)
发现在保存Order对象时为customerid字段赋值,因为Order对象中拥有Customer属性,对应customerid字段,查看数据库表:
- t_customer : t_order:
- id | name id | orderName | customerid
- 1 aaa 1 o1 NULL
- 2 o2 NULL
发现customerid的值仍为NULL,因为在上述代码中并未设置Order对象的Customer属性值,由于设置了inverse="true",所以Order对象需要维护关联关系,所以必须进行设置,即
order.setCustomer(customer);
修改上述代码为:
- •••
- Customer c = new Customer();
- Set orders = new HashSet();
- Order o1 = new Order();
- o1.setOrderName("o1");
- o1.setCustomer(c);
- Order o2 = new Order();
- o2.setOrderName("o2");
- o2.setCustomer(c);
- orders.add(o1);
- orders.add(o2);
- c.setName("aaa");
- c.setOrders(orders);
- session.save(c);
- •••
执行上述代码,发出如下语句:
- Hibernate: insert into t_customer (name) values (?)
- Hibernate: insert into t_order (orderName, customerid) values (?, ?)
- Hibernate: insert into t_order (orderName, customerid) values (?, ?)
查看数据库:
- t_customer : t_order:
- id | name id | orderName | customerid
- 1 aaa 1 o1 1
- 2 o2 1
发现已经设置了customerid的值。
在一对多关联中,在一的一方设置inverse="true"(即由多来维护!!),有助于性能的改善。通过上述分析可以发现少了update语句。
hibernate 一对多,由谁维护性能最优的更多相关文章
- hibernate 一对多双向关联 详解
一.解析: 1. 一对多双向关联也就是说,在加载班级时,能够知道这个班级所有的学生. 同时,在加载学生时,也能够知道这个学生所在的班级. 2.我们知道,一对多关联映射和多对一关联映射是一样的,都是在 ...
- Hibernate一对多OnetoMany
------------------------Hibernate一对多OnetoMany 要点: 配置在一端. 1.如果是单向关联,即只在一端配置OneToMany,多端不配置ManyToOne.则 ...
- Hibernate一对多单向关联和双向关联映射方法及其优缺点 (待续)
一对多关联映射和多对一关联映射实现的基本原理都是一样的,既是在多的一端加入一个外键指向一的一端外键,而主要的区别就是维护端不同.它们的区别在于维护的关系不同: 一对多关联映射是指在加载一的一端数据的同 ...
- Hibernate一对多操作
--------------------siwuxie095 Hibernate 一对多操作 以客户和联系人为例,客户是一,联系人是多 即 一个客户里面有多个联系人,一个联系人只能属于一个客户 注意: ...
- Hibernate一对多自关联、多对多关联
今天分享hibernate框架的两个关联关系 多对多关系注意事项 一定要定义一个主控方 多对多删除 主控方直接删除 被控方先通过主控方解除多对多关系,再删除被控方 禁用级联删除 关联关系编辑,不 ...
- Java进阶知识10 Hibernate一对多_多对一双向关联(Annotation+XML实现)
本文知识点(目录): 1.Annotation 注解版(只是测试建表) 2.XML版 的实现(只是测试建表) 3.附录(Annotation 注解版CRUD操作)[注解版有个问题:插入值时 ...
- hibernate一对多关联映射
一对多关联映射 映射原理 一对多关联映射和多对一关联映射的映射原理是一致的,都是在多的一端加入一个外键,指向一的一端.关联关系都是由多端维护,只是在写映射时发生了变化. 多对一和一对多的区别 多对一和 ...
- Hibernate一对多配置
刚刚学习了Hibernate框架的基础知识,下面我来说说关于Hibernate一对多的配置 首先是大配置 连接数据库 用户名 和密码 能和小配置连接 部门小配置: 员工小配置: 部门实体类 员工实体类 ...
- Spring / Hibernate 应用性能调优
来源:ImportNew - 陈晓舜 对大部分典型的Spring/Hibernate企业应用来说,应用的性能大部分由持久层的性能决定. 这篇文章会重温一下怎么去确认我们的应用是否是”数据库依赖(dat ...
随机推荐
- Numpy统计
Numpy统计 axis=None 是统计函数的标配参数,默认不输入此参数则为对数组每一个元素进行计算,设定轴则对此轴上元素进行计算 1:常用统计函数 .sum(a,axis=None):数组a求和运 ...
- HTML的实际演练1
1.HTML介绍 一个网站的建立都是HTML的,例如大家可以打开F12就可以看到浏览器的一个开发者模式,就可以看到网页的源代码了: 当然这网页他有很多的标签编写组成的,有的显示文字,段落,有的是个超链 ...
- javascript 中 if (window != top) top.location.href = location.href;的意思
如果当前窗口不是顶级窗口,就强制修改为顶级窗口: 目的是为了不让别人用iframe嵌入你的页面
- android笔记:Service
服务:在后台运行,没有界面的组件. 服务生命周期如下: 两种启动方式: 1.startService(): onCreate()-->onStartCommand()-->onDestro ...
- scrollLeft滚动(用animate替代)
原: let checkedLeft1 = $('#dateBox').find('.checked').position().left let checkedLeft2 = $('#dateBox' ...
- subprocess 粘包问题
1.执行命令: 在py代码中去如何调用操作系统的命令 新模块:subprocess r = subprocess.Popen('ls',shell=True,stdout=subprocess.PIP ...
- ios 进入后台 一段时间在进入前台 动画消失
http://www.cnblogs.com/YouXianMing/p/3670846.html
- iOS - 组件化探究之私有库的创建
http://www.cocoachina.com/ios/20180511/23359.html
- css hover使用条件
1:必须是其子元素才可以使用: 举例: css: 正确:.group-goodsList ul li:hover .msct{background-color: #ff4000;color: #FFF ...
- 《计算机网络》谢希仁(第7版) 第四章 c语言http://c.biancheng.net/cpp/html/3137.html
第四章 网络层 电信网使用面向连接的通信方式,使电信网络能够向用户提供可靠传输的服务. 互联网设计思路:网络层向上只提供简单灵活的.无连接的.尽最大努力交付的数据报(分组)服务. 网络层不提供可靠传输 ...