今天在javaeye上看到了这个文章,感觉超好.做下来看看....
前不久在搭建系统框架的时候遇到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.模型类
Java代码
- 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 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;
}
}
?
?
Java代码
- 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;??
- ????}??
- }??
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.配置文件
Java代码
- <!---->"1.0"?encoding="utf-8"?>??
- "-//Hibernate/Hibernate?Mapping?DTD?3.0//EN"??
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">??
- <!---->??
- <hibernate-mapping>??
- ????<class?name="domain.Customer"?table="customers"?catalog="blogday">??
- ????????<id?name=<span>"id">??
- ????????????<column?name=<span>"id"?/>??
- ????????????<generator?<span>class="native"></generator>??
- ????????</id>??
- ????????<property?name=<span>"name">??
- ????????????<column?name=<span>"name"?length="20"?/>??
- ????????</property>??
- ????????<set?name=<span>"orders"?lazy="true"?inverse="true"?cascade="all">??
- ????????????<key?column=<span>"customer_id"?/>??
- ????????????<one-to-many?<span>class="domain.Order"?/>??
- ????????</set>??
- ????<!---->class>??
- </hibernate-mapping>??
- ???
<!---->
<!---->
<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>
?
?
Java代码
- <!---->"1.0"?encoding="utf-8"?>??
- "-//Hibernate/Hibernate?Mapping?DTD?3.0//EN"??
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">??
- <!---->??
- <hibernate-mapping>??
- ????<class?name="domain.Order"?table="orders"?catalog="blogday">??
- ????????<id?name=<span>"id">??
- ????????????<column?name=<span>"id"?/>??
- ????????????<generator?<span>class="native"></generator>??
- ????????</id>??
- ????????<property?name=<span>"address">??
- ????????????<column?name=<span>"address"?length="20"?/>??
- ????????</property>??
- ????????<many-to-one?name=<span>"customer"?column="customer_id"??
- ????????????class="domain.Customer"?cascade="none"?/>??
- ????<!---->class>??
- </hibernate-mapping>??
<!---->
<!---->
<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.测试代码
Java代码
- 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);??
- ????}??
- ???????
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,用如下代码测试
Java代码
- 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);??
- ????}??
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);
}
?? 测试结果为:
?
Java代码
- 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: 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可以为空,这样下面的代码才不会 抛出错误
Java代码
- 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);??
- ????}??
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);
}
?测试结果:
Java代码
- 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=???
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,而且从性能上来说一般还是有字节点来维护与父节点的关系比较好如下代码就可以简单而且高效来建立二者之间的关系.
?
Java代码
- public?void?testSave()?{??
- ????Customer?customer?=?customerDao.findById("1");??
- ????Order?order?=?new?Order();??
- ????order.setCustomer(customer);??
- ????orderDao.save(order);??
- ????assertNotNull(order.getId());??
- }??
public void testSave() {
Customer customer = customerDao.findById("1");
Order order = new Order();
order.setCustomer(customer);
orderDao.save(order);
assertNotNull(order.getId());
}
?
这里的操作很简单而且数据库操作也仅有一条查询语句和一条插入语句.
?
Java代码
- 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?(?,??)??
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 (?, ?)
?
?
?
?
?
相关推荐
"NHibernate Inverse & Cascade"是两个关键概念,对于理解和有效使用NHibernate至关重要。 **Inverse属性** Inverse属性主要用于控制NHibernate如何处理关联对象的持久化。在一对多或多对一的关系中,当一个实体...
"IND Inverse - MetaTrader 4 脚本.zip" 是一个包含 MetaTrader 4 (MT4) 平台使用的自定义指标的压缩文件。这个指标被称为 "IND Inverse Indicator",它专为外汇交易者设计,帮助他们在市场分析中做出更明智的决策。...
逆向动力学(Inverse Kinematics)是计算机图形学和机器人技术中的一个重要领域,主要用于控制由多个关节连接的机械结构体的姿态。在动画制作和机器人运动规划中,逆向动力学问题的核心在于给定一个目标位置,计算出...
在探讨Hibernate的`inverse`属性之前,我们先要理解Hibernate中的对象关系映射(ORM)以及持久化机制。Hibernate是一个流行的Java ORM框架,它允许开发者将数据库操作转换为面向对象的编程模型,使得数据操作更加...
### Inverse Synthetic Aperture Radar (ISAR) Imaging与GPS数据应用 #### 摘要概述 逆合成孔径雷达(Inverse Synthetic Aperture Radar, ISAR)成像技术是一种利用雷达回波来生成高分辨率图像的技术。它在目标识别...
逆向动力学(Inverse Kinematics, IK)是机器人学中的一个重要概念,主要涉及如何通过机器人的关节角度来确定其末端执行器(如机械手爪)在空间中的位置和姿态。在MATLAB环境中实现逆向动力学,可以帮助我们更好地...
逆合成孔径雷达(Inverse Synthetic Aperture Radar, ISAR)是一种高级的雷达成像技术,它利用雷达系统在目标上移动或目标自身运动产生的相对运动,通过数学算法将接收到的回波数据处理成高分辨率的二维或三维图像。...
而"逆变换公园",即"transformation du park inverse",则是Park变换的反过程,用于将d、q坐标系的变量转换回原始的三相a、b、c坐标系。这一过程对于理解和实现交流电机的闭环控制具有核心地位。 Park变换的起源...
在计算机视觉和图像处理领域,"inverse perspective mapping (IPM)"是一种重要的技术,它用于将真实世界中的三维景象转换为二维图像上的鸟瞰视图,通常用于车辆监控、自动驾驶、地图绘制等领域。这个名为"IPM.zip_...
2. 导入库:在你的JavaScript代码中引入库,如`const inverse = require('array-inverse')`或现代模块系统中的`import inverse from 'array-inverse'`。 3. 使用逆阵功能:调用提供的函数,例如`inverse([1, 2, 3])`...
标题“3D_Math_Solve_Matrix_Inverse_by_Seamanj.rar”暗示了这是一个关于3D数学,具体涉及矩阵求逆方法的资料集合,由Seamanj提供。描述中提到了三种不同的求逆方法,分别是通过矩阵行列式、高斯-约当消元法以及LU...
逆向热传导(Inverse Heat Conduction)计算是热力学领域中的一个重要问题,它与传统的正向热传导计算相反。在正向热传导中,我们已知初始条件和边界条件,来预测物体内部温度分布;而在逆向热传导中,目标是通过...
在这篇论文中,还提出了使用逆深度(inverse depth)作为三维点估计的编码方式。逆深度参数化是一种避免了深度先验知识的初始化方法,特别适用于远距离特征点的估计。这种方法相较于传统的XYZ编码,即使对于那些视差...
文件"Inverse_transformation_2.r"可能包含了一个实际的逆变换算法的实现,或者是一组用于测试逆变换效果的数据。 逆变换在许多领域都有广泛的应用。在信号处理中,逆变换常用于信号恢复或去噪。例如,在音频处理中...
《信号与系统》课程中的第五章第三部分主要讨论了逆变换的方法,特别是在频率域中线性时不变(LTI)系统的分析。这部分内容是信号处理和系统理论的基础,对于理解和设计滤波器至关重要。 首先,5.1节提到了信息选择...