引用myqhit在one-many和many-one的关系中的inverse的详解。
1.现在假设有两个类Customer与Order,一个Customer可以有多个Order
2. 如果在Customer.hbm.xml中设置inverse=投入额,那么代表customer与order的关系由order来维护,就是说如果采用 Customer c=customerDao.findById("1"),c.getOrders.add(new Order()),那么在数据库层面表现为,首先假设在order表格中customer_id可以为空,那么上面的代码会在order表中重保存一条 order记录,但是这条纪录中的customer_id=null,这正体现出inverse的设置作用,customer的保存不会维护 ustomer与order之间的关系。
3.如果在Customer.hbm.xml中设置iverser=false,那么代表customer与order的关系由customer来维护,
还是采用2种说明的代码,那么在数据库中表现为会增加一条order记录,并且这条记录的customer_d不为空.
具体代码说明:
1.模型类
public class Customer {
private String id;
private String name;
private Set orders = new HashSet();
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set getOrders() {
return orders;
}
public void setOrders(Set orders) {
this.orders = orders;
}
}
public class Order {
private String id;
private Customer customer;
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
1.配置文件
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse - Hibernate Tools
-->
<hibernate-mapping>
<class name="domain.Customer" table="customers" catalog="blogday">
<id name="id">
<column name="id" />
<generator class="native"></generator>
</id>
<property name="name">
<column name="name" length="20" />
</property>
<set name="orders" lazy="true" inverse="true" cascade="all">
<key column="customer_id" />
<one-to-many class="domain.Order" />
</set>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse - Hibernate Tools
-->
<hibernate-mapping>
<class name="domain.Order" table="orders" catalog="blogday">
<id name="id">
<column name="id" />
<generator class="native"></generator>
</id>
<property name="address">
<column name="address" length="20" />
</property>
<many-to-one name="customer" column="customer_id"
class="domain.Customer" cascade="none" />
</class>
</hibernate-mapping>
3.测试代码
public void testSaveOrdersByInverse_Error_Method() {
Exception e = null;
Customer c = customerDao.findById("1");
Order order = new Order();
Order order2 = new Order();
c.getOrders().add(order2);
c.getOrders().add(order);
try {
customerDao.save(c);
customerDao.getHibernateTemplate().flush();
} catch (Exception e1) {
e = e1;
}
assertNotNull(e);
}
4. 结果说明
4.1 如果设置invserse=true,那么方法testSaveOrdersByInverse_Error_Method()在测试的时候
customerDao.getHibernateTemplate().flush()进行flush的时候会发生错误,错误原因是在order表格中
不允许customer_id=null,而在此时方法testSaveOrdersByInverse_Error_Method会级联保存order记录,但是保存的order记录中hibernate却设置customer_id=null,这也说明了inverse=true说明customer不负责与order之间的引用关系,只是简单的保存记录,并没有建立起二者之间的关系.
4.2如果设置inverse =false,说明customer与order之间的关系由customer来维护,那么上面的测试方法 testSaveOrdersByInverse_Error_Method()不但会保存相应的order记录,并且order记录中的 customer_id也不为空.
5.性能考虑
5.1 如果设置inverse=true,用如下代码测试
public void testSaveOrdersByInverse_Right_method() {
Exception e = null;
Customer c = customerDao.findById("1");
Order order1 = new Order();
Order order2 = new Order();
c.getOrders().add(order1);
c.getOrders().add(order2);
order1.setCustomer(c);
order2.setCustomer(c);
try {
customerDao.save(c);
customerDao.getHibernateTemplate().flush();
} catch (Exception e1) {
e = e1;
}
assertNull(e);
}
测试结果为:
Hibernate: select orders0_.customer_id as customer3_1_, orders0_.id as id1_, orders0_.id as id1_0_, orders0_.address as address1_0_, orders0_.customer_id as customer3_1_0_ from blogday.orders orders0_ where orders0_.customer_id=?
Hibernate: insert into blogday.orders (address, customer_id) values (?, ?)
Hibernate: insert into blogday.orders (address, customer_id) values (?, ?)
说明没插入一条order只需要执行一次插入操作,没有额外的代码执行.
5.2 如果设置inverse=false,也顺便设置数据库中order表格中customer_id可以为空,这样下面的代码才不会 抛出错误
public void testSaveOrdersByInverse_Error_Method() {
Exception e = null;
Customer c = customerDao.findById("1");
Order order1 = new Order();
Order order2 = new Order();
c.getOrders().add(order1);
c.getOrders().add(order2);
try {
customerDao.save(c);
customerDao.getHibernateTemplate().flush();
} catch (Exception e1) {
e = e1;
}
assertNull(e);
}
测试结果:
Hibernate: select customer0_.id as id0_0_, customer0_.name as name0_0_ from blogday.customers customer0_ where customer0_.id=?
Hibernate: select orders0_.customer_id as customer3_1_, orders0_.id as id1_, orders0_.id as id1_0_, orders0_.address as address1_0_, orders0_.customer_id as customer3_1_0_ from blogday.orders orders0_ where orders0_.customer_id=?
Hibernate: insert into blogday.orders (address, customer_id) values (?, ?)
Hibernate: insert into blogday.orders (address, customer_id) values (?, ?)
Hibernate: update blogday.orders set customer_id=? where id=?
Hibernate: update blogday.orders set customer_id=? where id=?
插入customer也会相应的插入order记录,这个在上面已经说明.但是看这里多出了两条update语句,针对每一个孩子都去更新父亲的id明显速度很慢,因为父亲有个孩子的集合,他无法知道哪个孩子的父亲id已经指向自己了,所以对于每一个孩子,都要更新父亲使他只想自己,而这个关系由孩子维护就好多了,每个孩子只有一个父亲,只有设置过的才需要更新,所以显然,这个父子关系由孩子来维护比较省力.减轻了数据库的负担.
正对以上情况在设置one-many或者many-one或者many-many的时候需要谨慎用inverse,而且从性能上来说一般还是有字节点来维护与父节点的关系比较好如下代码就可以简单而且高效来建立二者之间的关系.
public void testSave() {
Customer customer = customerDao.findById("1");
Order order = new Order();
order.setCustomer(customer);
orderDao.save(order);
assertNotNull(order.getId());
}
这里的操作很简单而且数据库操作也仅有一条查询语句和一条插入语句.
Hibernate: select customer0_.id as id0_0_, customer0_.name as name0_0_ from blogday.customers customer0_ where customer0_.id=?
Hibernate: insert into blogday.orders (address, customer_id) values (?, ?)
分享到:
相关推荐
旋转检测 要求 torch==1.6 shapely==1.7.1 opencv==4.2.0.34
1.版本:matlab2014/2019a/2021a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
基于springboot的java毕业&课程设计
智慧藏文化博物馆建设方案PPT(79页)
基于springboot的java毕业&课程设计
动作识别_基于OpenPose实现的实时姿态估计+动作识别_附项目源码_优质项目实战
机器学习之随机森林算法
反弹shell
该系统是针对各类学院或者研究院的项目管理而设计开发的。它实现了项目的各类信息的录入、修改、查询和报表打印等功能,这些信息主要包括项目的基本情况、项目进展程度、项目经费开支、以及科研成果和项目获奖情况等。该系统界面友好清晰,使用方便快捷,它简化了项目的管理过程,提高了科研管理人员的工作效率,从而节省了人力资源与经费开支,有利于经济效益的提高和科研事业的发展。
STM32/GD32 I2C DMA 主从通信 定长主从通信代码示例
课设毕设基于SSM的大学生兼职跟踪系统 LW+PPT+源码可运行.zip
巨灾保险问题及对策研究.docx
卷积神经网络(Convolutional Neural Networks, CNNs 或 ConvNets)是一类深度神经网络,特别擅长处理图像相关的机器学习和深度学习任务。它们的名称来源于网络中使用了一种叫做卷积的数学运算。以下是卷积神经网络的一些关键组件和特性: 卷积层(Convolutional Layer): 卷积层是CNN的核心组件。它们通过一组可学习的滤波器(或称为卷积核、卷积器)在输入图像(或上一层的输出特征图)上滑动来工作。 滤波器和图像之间的卷积操作生成输出特征图,该特征图反映了滤波器所捕捉的局部图像特性(如边缘、角点等)。 通过使用多个滤波器,卷积层可以提取输入图像中的多种特征。 激活函数(Activation Function): 在卷积操作之后,通常会应用一个激活函数(如ReLU、Sigmoid或tanh)来增加网络的非线性。 池化层(Pooling Layer): 池化层通常位于卷积层之后,用于降低特征图的维度(空间尺寸),减少计算量和参数数量,同时保持特征的空间层次结构。 常见的池化操作包括最大池化(Max Pooling)和平均池化(Average Po
Unity插件 Translucent Image 可帮助你构建精美的模糊背景 UI,例如在 iOS/MacOS/Windows 10 Fluent 设计中的 UI。 与许多其他背景模糊解决方案不同,Translucent Image 采用一种对性能影响最小的高效算法,因此用户可以享受更高的帧速率和更长的电池寿命。不仅如此,当你将模糊调高时,它还可以产生完美的平滑效果,而其它资源在高度模糊时会呈现难看的块状图像。
微信小程序设计之相关行业源码及图文导入教程
react中的组件定义
课程设计 基于Python的机器学习的人脸识别系统的设计与实现+详细文档+全部资料(高分项目).zip本资源中的源码都是经过本地编译过可运行的,评审分达到95分以上。资源项目的难度比较适中,内容都是经过助教老师审定过的能够满足学习、使用需求,如果有需要的话可以放心下载使用。 课程设计 基于Python的机器学习的人脸识别系统的设计与实现+详细文档+全部资料(高分项目).zip本资源中的源码都是经过本地编译过可运行的,评审分达到95分以上。资源项目的难度比较适中,内容都是经过助教老师审定过的能够满足学习、使用需求,如果有需要的话可以放心下载使用。 课程设计 基于Python的机器学习的人脸识别系统的设计与实现+详细文档+全部资料(高分项目).zip本资源中的源码都是经过本地编译过可运行的,评审分达到95分以上。资源项目的难度比较适中,内容都是经过助教老师审定过的能够满足学习、使用需求,如果有需要的话可以放心下载使用。 课程设计 基于Python的机器学习的人脸识别系统的设计与实现+详细文档+全部资料(高分项目).zip本资源中的源码都是经过本地编译过可运行的,评审分达到95分以上。
微信小程序设计之相关行业源码及图文导入教程
AndroidStudio_WiFiManager-master
【微电网优化】粒子群优化算法的微电网调度(光伏、储能、电动车、电网交互)【含Matlab源码 2190期】.zip