﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-yuwenlin-随笔分类-Hibernate</title><link>http://www.blogjava.net/yuwenlin/category/39047.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 15 Oct 2009 18:03:30 GMT</lastBuildDate><pubDate>Thu, 15 Oct 2009 18:03:30 GMT</pubDate><ttl>60</ttl><item><title>精通Hibernate——映射一对多关联关系</title><link>http://www.blogjava.net/yuwenlin/archive/2009/10/16/298483.html</link><dc:creator>独孤行</dc:creator><author>独孤行</author><pubDate>Thu, 15 Oct 2009 16:29:00 GMT</pubDate><guid>http://www.blogjava.net/yuwenlin/archive/2009/10/16/298483.html</guid><wfw:comment>http://www.blogjava.net/yuwenlin/comments/298483.html</wfw:comment><comments>http://www.blogjava.net/yuwenlin/archive/2009/10/16/298483.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/yuwenlin/comments/commentRss/298483.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/yuwenlin/services/trackbacks/298483.html</trackback:ping><description><![CDATA[<p>在域模型(实体域)中，关联关系是类与类之间最普遍的关系。根据UML语言，关系是有方向的。下面以客户(Customer)和订单(Order)的关系为例，阐述一下ORM的中的一对多映射：<br />
我们知道，在关系数据库中，只存在外键参照关系，而且总是由&#8220;many&#8221;方参照&#8220;one&#8220;方。<br />
1.建立多对一单向关联——Order(many)---&gt;Customer(one)：<br />
-------------------------------Order.java--------------------------------</p>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000">pack&nbsp;mypack;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.io.Serializable;<br />
<img id="Codehighlighter1_84_198_Open_Image" onclick="this.style.display='none'; Codehighlighter1_84_198_Open_Text.style.display='none'; Codehighlighter1_84_198_Closed_Image.style.display='inline'; Codehighlighter1_84_198_Closed_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_84_198_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_84_198_Closed_Text.style.display='none'; Codehighlighter1_84_198_Open_Image.style.display='inline'; Codehighlighter1_84_198_Open_Text.style.display='inline';" alt="" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;Order&nbsp;</span><span style="color: #0000ff">implements</span><span style="color: #000000">&nbsp;Serializable</span><span id="Codehighlighter1_84_198_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img alt="" src="http://www.blogjava.net/Images/dot.gif" /></span><span id="Codehighlighter1_84_198_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;id;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;String&nbsp;orderNumber;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;Customer&nbsp;customer;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">构造方法及set方法get方法</span><span style="color: #008000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;<img alt="" src="http://www.blogjava.net/Images/dot.gif" /><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span></div>
在以上代码中customer属性要使用&lt;many-to-one&gt;来映射：<br />
<span style="color: #ff0000">多对一单向关联(many方)</span><br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000">&lt;</span><span style="color: #000000">many</span><span style="color: #000000">-</span><span style="color: #000000">to</span><span style="color: #000000">-</span><span style="color: #000000">one</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;name&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">customer</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">--</span><span style="color: #000000">待映射的持久化类属性名<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;column&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">customer_Id</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;&nbsp;</span><span style="color: #000000">--</span><span style="color: #000000">数据库外键字段<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">mypack.Customer</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;&nbsp;</span><span style="color: #000000">--</span><span style="color: #000000">持久化类<br />
<img alt="" src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;not</span><span style="color: #000000">-</span><span style="color: #0000ff">null</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">true</span><span style="color: #000000">"</span><span style="color: #000000">/&gt;</span></div>
<span style="color: #ff0000"><span style="color: #333333"><strong>a.&nbsp; &lt;many-to-one&gt;的not-null属性</strong>&nbsp;</span></span> <br />
not-null属性会影响Hiberntae的运行时行为，Hibernate在保存Order对象时，会先检查它的customer属性是否为null：<br />
若为null：在执行session.save(Order)时会抛出PropertyValueException异常；<br />
原因很简单：既然Customer为null，那么对应的外键Customer_Id也为null，试问外键都没有，Order表的数据能插得进去吗<br />
若将not-null 属性设为false：表示外键引用可以为null，试想一下，数据库数据可以插进去吗？<br />
我们来看：在执行session.save(Order)时，发出了sql语句：insert into......<br />
但是当Hibernate自动清理(flush)缓存时，抛出新的异常：TransientObjectException<br />
所谓清理是提交事务或手动Flush，将session与数据库保持同步，很显然不可能同步嘛，Order对象虽然持久化，但Customer没有.<br />
<span style="color: #333333">&nbsp;&nbsp;&nbsp;&nbsp;<strong>注：</strong><span style="color: #ff0000">是否应该把&lt;many-to-one&gt;的not-null属性设为true，这根据实际业务而定。通常，订单总是由客户自己发出，因此建议设为true.<br />
</span><span style="color: #333333"><strong>b.&nbsp; 级联保存与更新</strong></span><br />
默认情况下，Hibernate持久化一个对象，不会自动持久化所关联的其它临时对象，因此会有TransientObjectException，<br />
想它关联也可以，&lt;many-to-one&gt;中加个属性cascade="save-update"即可.<br />
<br />
2.建立一对多关联——Customer(one)---&gt;Order(many)：<br />
-----------------------------Customer.java-------------------------------<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #0000ff">package</span><span style="color: #000000">&nbsp;mypack;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /><br />
<img id="Codehighlighter1_72_182_Open_Image" onclick="this.style.display='none'; Codehighlighter1_72_182_Open_Text.style.display='none'; Codehighlighter1_72_182_Closed_Image.style.display='inline'; Codehighlighter1_72_182_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_72_182_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_72_182_Closed_Text.style.display='none'; Codehighlighter1_72_182_Open_Image.style.display='inline'; Codehighlighter1_72_182_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;calss&nbsp;Customer&nbsp;</span><span style="color: #0000ff">implements</span><span style="color: #000000">&nbsp;Serlizliab;e</span><span id="Codehighlighter1_72_182_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_72_182_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;id;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;String&nbsp;name;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;Set&nbsp;orders&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;HsahSet();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">构造方法及set方法get方法</span><span style="color: #008000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" /></span><span style="color: #000000">}</span></span></div>
<span style="color: #ff0000">一对多关联(one方)</span><br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">&lt;</span><span style="color: #000000">set&nbsp;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">orders</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;&nbsp;</span><span style="color: #000000">--</span><span style="color: #000000">持久化对象的属性<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cascade&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">save-update</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">--</span><span style="color: #000000">级联操作<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">key&nbsp;cloumn&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">customer_Id</span><span style="color: #000000">"</span><span style="color: #000000">/&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">--</span><span style="color: #000000">外键<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">one</span><span style="color: #000000">-</span><span style="color: #000000">to</span><span style="color: #000000">-</span><span style="color: #000000">many&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">mypack.Order</span><span style="color: #000000">"</span><span style="color: #000000">/&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">--</span><span style="color: #000000">持久化类<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #000000">&lt;/</span><span style="color: #000000">set</span><span style="color: #000000">&gt;</span></div>
<strong>a.&nbsp; &lt;set&gt;元素的inverse属性</strong><br />
　　在映射一对多的双向关联时，应该在&#8220;one&#8221;方把inverse属性设为true，这样可提高应用性能。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inverse：控制反转，为true表示反转，由它方负责；反之，不反转，自己负责；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果不设，one和many两方都要负责控制，因此，会引发重复的sql语句以及重复添加数据，<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在建立两个象的双向关系时，应该同时修改关联两端的对象属性：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff0000">customer.getOrders().add(order);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;order.setCustomer(customer);</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;这样做可提高业务逻辑的独立性，使业务逻辑的程序代码不受Hibernate实现的影响。同理解除双向关系也一样。<br />
<strong>b.&nbsp;&nbsp;级联删除(从数据库删除相关表记录)<br />
</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff0000">当删除Customer对象时，及联删除Order对象.只需将cascad属性设为delete即可.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #333333">&nbsp;<strong>注：</strong></span>删除后的对象，依然存在于内存中，只不过由持久化态变为临时态.<br />
</span><strong>c.&nbsp;&nbsp;父子关系(逻辑删除，只是解除了关联关系)</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #ff0000">自动删除不再和Customer对象关联的Order对象.只需将cascade属性设为delete-orphan.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;customer.getOrders().remove(order);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; order.setCustomer(null);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong style="color: #333333">注：</strong>当关联双方都存在父子关系，就可以把父方的cascade属性设为delete-orphan，所谓父子关系，是由父方来控制子方的生命周期.<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
<br />
<br />
</span>
<img src ="http://www.blogjava.net/yuwenlin/aggbug/298483.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/yuwenlin/" target="_blank">独孤行</a> 2009-10-16 00:29 <a href="http://www.blogjava.net/yuwenlin/archive/2009/10/16/298483.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>