HIbernate中inverse的用法

本文深入解析了Hibernate框架中“inverse”属性的作用,并通过实例演示如何使用该属性优化一对多关系的性能。
Always put inverse=”true” in your collection variable ?
There are many Hibernate articles try to explain the “inverse” with many Hibernate “official” jargon, which is very hard to understand (at least to me). In few articles, they even suggested that just forget about what is “inverse”, and always put inverse=”true” in the collection variable.

This statement is always true – “put inverse=true in collection variable”, but do not blindfold on it, try to understand the reason behind is essential to optimal your Hibernate performance.

 

What is “inverse” ?

This is the most confusing keyword in Hibernate, at least i took quite a long time to understand it. The “inverse” keyword is always declare in one-to-many and many-to-many relationship (many-to-one doesn’t has inverse keyword), it means which side is responsible to take care of the relationship.

 

“inverse”, should change to “relationship owner”?

In Hibernate, only the “relationship owner” should maintain the relationship, and the “inverse” keyword is created to defines which side is the owner to maintain the relationship. However the “inverse” keyword itself is not verbose enough, I would suggest change the keyword to “relationship_owner“.

In short, inverse=”true” means this is the relationship owner, and inverse=”false” (default) means it’s not.

 

 

举例如下

Customer类:
public class Customer { 
	private int id; 
	private String name;
private Set orders = new HashSet();
//getter / setter
}

即Customer类具有一个set集合属性orders,其中Order是一个普通的类:
public class Order { 
	private int id; 
	private String orderName;
//getter / setter
}

数据库中表的结构:
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语句。

 

考虑柔性负荷的综合能源系统低碳经济优化调度【考虑碳交易机制】(Matlab代码实现)内容概要:本文围绕“考虑柔性负荷的综合能源系统低碳经济优化调度”展开,重点研究在碳交易机制下如何实现综合能源系统的低碳化与经济性协同优化。通过构建包含风电、光伏、储能、柔性负荷等多种能源形式的系统模型,结合碳交易成本与能源调度成本,提出优化调度策略,以降低碳排放并提升系统运行经济性。文中采用Matlab进行仿真代码实现,验证了所提模型在平衡能源供需、平抑可再生能源波动、引导柔性负荷参与调度等方面的有效性,为低碳能源系统的设计与运行提供了技术支撑。; 适合人群:具备一定电力系统、能源系统背景,熟悉Matlab编程,从事能源优化、低碳调度、综合能源系统等相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①研究碳交易机制对综合能源系统调度决策的影响;②实现柔性负荷在削峰填谷、促进可再生能源消纳中的作用;③掌握基于Matlab的能源系统建模与优化求解方法;④为实际综合能源项目提供低碳经济调度方案参考。; 阅读建议:建议读者结合Matlab代码深入理解模型构建与求解过程,重点关注目标函数设计、约束条件设置及碳交易成本的量化方式,可进一步扩展至多能互补、需求响应等场景进行二次开发与仿真验证。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值