﻿<?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-liuqiang5151-文章分类-Hibernate</title><link>http://www.blogjava.net/liuqiang5151/category/25845.html</link><description /><language>zh-cn</language><lastBuildDate>Sat, 12 Apr 2008 03:11:48 GMT</lastBuildDate><pubDate>Sat, 12 Apr 2008 03:11:48 GMT</pubDate><ttl>60</ttl><item><title>深入理解HibernateTemplate机制</title><link>http://www.blogjava.net/liuqiang5151/articles/192255.html</link><dc:creator>刘强</dc:creator><author>刘强</author><pubDate>Fri, 11 Apr 2008 10:34:00 GMT</pubDate><guid>http://www.blogjava.net/liuqiang5151/articles/192255.html</guid><wfw:comment>http://www.blogjava.net/liuqiang5151/comments/192255.html</wfw:comment><comments>http://www.blogjava.net/liuqiang5151/articles/192255.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liuqiang5151/comments/commentRss/192255.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liuqiang5151/services/trackbacks/192255.html</trackback:ping><description><![CDATA[拿个例子来看<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 id="Codehighlighter1_64_115_Open_Image" onclick="this.style.display='none'; Codehighlighter1_64_115_Open_Text.style.display='none'; Codehighlighter1_64_115_Closed_Image.style.display='inline'; Codehighlighter1_64_115_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_64_115_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_64_115_Closed_Text.style.display='none'; Codehighlighter1_64_115_Open_Image.style.display='inline'; Codehighlighter1_64_115_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;persist(</span><span style="color: #0000ff">final</span><span style="color: #000000">&nbsp;Object&nbsp;entity,&nbsp;</span><span style="color: #0000ff">final</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">boolean</span><span style="color: #000000">&nbsp;isFlush)&nbsp;</span><span id="Codehighlighter1_64_115_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_64_115_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getHibernateTemplate().persist(entity);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />&nbsp;}</span></span></div>
HibernateTemplate源码：<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 id="Codehighlighter1_68_287_Open_Image" onclick="this.style.display='none'; Codehighlighter1_68_287_Open_Text.style.display='none'; Codehighlighter1_68_287_Closed_Image.style.display='inline'; Codehighlighter1_68_287_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_68_287_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_68_287_Closed_Text.style.display='none'; Codehighlighter1_68_287_Open_Image.style.display='inline'; Codehighlighter1_68_287_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;persist(</span><span style="color: #0000ff">final</span><span style="color: #000000">&nbsp;Object&nbsp;entity)&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;DataAccessException&nbsp;</span><span id="Codehighlighter1_68_287_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_68_287_Open_Text"><span style="color: #000000">{<br />
<img id="Codehighlighter1_104_276_Open_Image" onclick="this.style.display='none'; Codehighlighter1_104_276_Open_Text.style.display='none'; Codehighlighter1_104_276_Closed_Image.style.display='inline'; Codehighlighter1_104_276_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_104_276_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_104_276_Closed_Text.style.display='none'; Codehighlighter1_104_276_Open_Image.style.display='inline'; Codehighlighter1_104_276_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;execute(</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;HibernateCallback()&nbsp;</span><span id="Codehighlighter1_104_276_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_104_276_Open_Text"><span style="color: #000000">{<br />
<img id="Codehighlighter1_180_272_Open_Image" onclick="this.style.display='none'; Codehighlighter1_180_272_Open_Text.style.display='none'; Codehighlighter1_180_272_Closed_Image.style.display='inline'; Codehighlighter1_180_272_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_180_272_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_180_272_Closed_Text.style.display='none'; Codehighlighter1_180_272_Open_Image.style.display='inline'; Codehighlighter1_180_272_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;Object&nbsp;doInHibernate(Session&nbsp;session)&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;HibernateException&nbsp;</span><span id="Codehighlighter1_180_272_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_180_272_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;checkWriteOperationAllowed(session);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session.persist(entity);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">null</span><span style="color: #000000">;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">,&nbsp;</span><span style="color: #0000ff">true</span><span style="color: #000000">);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></div>
<br />
我们可以看到，在他的内部，执行的是一个名叫execute的方法，这里无论是persist方法还是update方法，到这里都会执行这个方法，看过设计模式的人可能很清楚，这个类似于封装调用。就是调用者不需要知道接受者是如何实现的，只知道调用execute这个方法就行了。方法里的参数是个接口类型。让我们来看看HibernateCallback这个接口是如何定义的。<br />
HibernateCallback.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 id="Codehighlighter1_35_118_Open_Image" onclick="this.style.display='none'; Codehighlighter1_35_118_Open_Text.style.display='none'; Codehighlighter1_35_118_Closed_Image.style.display='inline'; Codehighlighter1_35_118_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_35_118_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_35_118_Closed_Text.style.display='none'; Codehighlighter1_35_118_Open_Image.style.display='inline'; Codehighlighter1_35_118_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">interface</span><span style="color: #000000">&nbsp;HibernateCallback&nbsp;</span><span id="Codehighlighter1_35_118_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_35_118_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;doInHibernate(Session&nbsp;session)&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;HibernateException,&nbsp;SQLException;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span></div>
这个接口就一个方法，我在上面传递的参数就是实现这个方法的类，匿名内部类可能看的不好懂，也可以这么理解。<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 id="Codehighlighter1_68_114_Open_Image" onclick="this.style.display='none'; Codehighlighter1_68_114_Open_Text.style.display='none'; Codehighlighter1_68_114_Closed_Image.style.display='inline'; Codehighlighter1_68_114_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_68_114_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_68_114_Closed_Text.style.display='none'; Codehighlighter1_68_114_Open_Image.style.display='inline'; Codehighlighter1_68_114_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;persist(</span><span style="color: #0000ff">final</span><span style="color: #000000">&nbsp;Object&nbsp;entity)&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;DataAccessException&nbsp;</span><span id="Codehighlighter1_68_114_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_68_114_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HibernateCallbackImplForPersist(),</span><span style="color: #0000ff">true</span><span style="color: #000000">);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></div>
可以理解为HibernateCallbackImplForPersist这个类实现了HibernateCallback接口，实现代码就是上面的doInHibernate()方法。<br />
<br />
execute()方法<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"><span style="color: #008080">&nbsp;1</span><img id="Codehighlighter1_104_1565_Open_Image" onclick="this.style.display='none'; Codehighlighter1_104_1565_Open_Text.style.display='none'; Codehighlighter1_104_1565_Closed_Image.style.display='inline'; Codehighlighter1_104_1565_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_104_1565_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_104_1565_Closed_Text.style.display='none'; Codehighlighter1_104_1565_Open_Image.style.display='inline'; Codehighlighter1_104_1565_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;Object&nbsp;execute(HibernateCallback&nbsp;action,&nbsp;</span><span style="color: #0000ff">boolean</span><span style="color: #000000">&nbsp;exposeNativeSession)&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;DataAccessException&nbsp;</span><span id="Codehighlighter1_104_1565_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_104_1565_Open_Text"><span style="color: #000000">{<br />
</span><span style="color: #008080">&nbsp;2</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Assert.notNull(action,&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">Callback&nbsp;object&nbsp;must&nbsp;not&nbsp;be&nbsp;null</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
</span><span style="color: #008080">&nbsp;3</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
</span><span style="color: #008080">&nbsp;4</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Session&nbsp;session&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;getSession();<br />
</span><span style="color: #008080">&nbsp;5</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">boolean</span><span style="color: #000000">&nbsp;existingTransaction&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;SessionFactoryUtils.isSessionTransactional(session,&nbsp;getSessionFactory());<br />
</span><span style="color: #008080">&nbsp;6</span><span style="color: #000000"><img id="Codehighlighter1_336_409_Open_Image" onclick="this.style.display='none'; Codehighlighter1_336_409_Open_Text.style.display='none'; Codehighlighter1_336_409_Closed_Image.style.display='inline'; Codehighlighter1_336_409_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_336_409_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_336_409_Closed_Text.style.display='none'; Codehighlighter1_336_409_Open_Image.style.display='inline'; Codehighlighter1_336_409_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(existingTransaction)&nbsp;</span><span id="Codehighlighter1_336_409_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_336_409_Open_Text"><span style="color: #000000">{<br />
</span><span style="color: #008080">&nbsp;7</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.debug(</span><span style="color: #000000">"</span><span style="color: #000000">Found&nbsp;thread-bound&nbsp;Session&nbsp;for&nbsp;HibernateTemplate</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
</span><span style="color: #008080">&nbsp;8</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
</span><span style="color: #008080">&nbsp;9</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
</span><span style="color: #008080">10</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FlushMode&nbsp;previousFlushMode&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">null</span><span style="color: #000000">;<br />
</span><span style="color: #008080">11</span><span style="color: #000000"><img id="Codehighlighter1_456_775_Open_Image" onclick="this.style.display='none'; Codehighlighter1_456_775_Open_Text.style.display='none'; Codehighlighter1_456_775_Closed_Image.style.display='inline'; Codehighlighter1_456_775_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_456_775_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_456_775_Closed_Text.style.display='none'; Codehighlighter1_456_775_Open_Image.style.display='inline'; Codehighlighter1_456_775_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">try</span><span style="color: #000000">&nbsp;</span><span id="Codehighlighter1_456_775_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_456_775_Open_Text"><span style="color: #000000">{<br />
</span><span style="color: #008080">12</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;previousFlushMode&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;applyFlushMode(session,&nbsp;existingTransaction);<br />
</span><span style="color: #008080">13</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;enableFilters(session);<br />
</span><span style="color: #008080">14</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Session&nbsp;sessionToExpose&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;(exposeNativeSession&nbsp;</span><span style="color: #000000">?</span><span style="color: #000000">&nbsp;session&nbsp;:&nbsp;createSessionProxy(session));<br />
</span><span style="color: #008080">15</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;result&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;action.doInHibernate(sessionToExpose);<br />
</span><span style="color: #008080">16</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;flushIfNecessary(session,&nbsp;existingTransaction);<br />
</span><span style="color: #008080">17</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;result;<br />
</span><span style="color: #008080">18</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
</span><span style="color: #008080">19</span><span style="color: #000000"><img id="Codehighlighter1_809_859_Open_Image" onclick="this.style.display='none'; Codehighlighter1_809_859_Open_Text.style.display='none'; Codehighlighter1_809_859_Closed_Image.style.display='inline'; Codehighlighter1_809_859_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_809_859_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_809_859_Closed_Text.style.display='none'; Codehighlighter1_809_859_Open_Image.style.display='inline'; Codehighlighter1_809_859_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">catch</span><span style="color: #000000">&nbsp;(HibernateException&nbsp;ex)&nbsp;</span><span id="Codehighlighter1_809_859_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_809_859_Open_Text"><span style="color: #000000">{<br />
</span><span style="color: #008080">20</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">throw</span><span style="color: #000000">&nbsp;convertHibernateAccessException(ex);<br />
</span><span style="color: #008080">21</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
</span><span style="color: #008080">22</span><span style="color: #000000"><img id="Codehighlighter1_887_932_Open_Image" onclick="this.style.display='none'; Codehighlighter1_887_932_Open_Text.style.display='none'; Codehighlighter1_887_932_Closed_Image.style.display='inline'; Codehighlighter1_887_932_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_887_932_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_887_932_Closed_Text.style.display='none'; Codehighlighter1_887_932_Open_Image.style.display='inline'; Codehighlighter1_887_932_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">catch</span><span style="color: #000000">&nbsp;(SQLException&nbsp;ex)&nbsp;</span><span id="Codehighlighter1_887_932_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_887_932_Open_Text"><span style="color: #000000">{<br />
</span><span style="color: #008080">23</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">throw</span><span style="color: #000000">&nbsp;convertJdbcAccessException(ex);<br />
</span><span style="color: #008080">24</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
</span><span style="color: #008080">25</span><span style="color: #000000"><img id="Codehighlighter1_964_1032_Open_Image" onclick="this.style.display='none'; Codehighlighter1_964_1032_Open_Text.style.display='none'; Codehighlighter1_964_1032_Closed_Image.style.display='inline'; Codehighlighter1_964_1032_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_964_1032_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_964_1032_Closed_Text.style.display='none'; Codehighlighter1_964_1032_Open_Image.style.display='inline'; Codehighlighter1_964_1032_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">catch</span><span style="color: #000000">&nbsp;(RuntimeException&nbsp;ex)&nbsp;</span><span id="Codehighlighter1_964_1032_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_964_1032_Open_Text"><span style="color: #000000">{<br />
</span><span style="color: #008080">26</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;Callback&nbsp;code&nbsp;threw&nbsp;application&nbsp;exception<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span style="color: #008000"><br />
</span><span style="color: #008080">27</span><span style="color: #008000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">throw</span><span style="color: #000000">&nbsp;ex;<br />
</span><span style="color: #008080">28</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
</span><span style="color: #008080">29</span><span style="color: #000000"><img id="Codehighlighter1_1044_1562_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1044_1562_Open_Text.style.display='none'; Codehighlighter1_1044_1562_Closed_Image.style.display='inline'; Codehighlighter1_1044_1562_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1044_1562_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1044_1562_Closed_Text.style.display='none'; Codehighlighter1_1044_1562_Open_Image.style.display='inline'; Codehighlighter1_1044_1562_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">finally</span><span style="color: #000000">&nbsp;</span><span id="Codehighlighter1_1044_1562_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_1044_1562_Open_Text"><span style="color: #000000">{<br />
</span><span style="color: #008080">30</span><span style="color: #000000"><img id="Codehighlighter1_1074_1282_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1074_1282_Open_Text.style.display='none'; Codehighlighter1_1074_1282_Closed_Image.style.display='inline'; Codehighlighter1_1074_1282_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1074_1282_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1074_1282_Closed_Text.style.display='none'; Codehighlighter1_1074_1282_Open_Image.style.display='inline'; Codehighlighter1_1074_1282_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(existingTransaction)&nbsp;</span><span id="Codehighlighter1_1074_1282_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_1074_1282_Open_Text"><span style="color: #000000">{<br />
</span><span style="color: #008080">31</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logger.debug(</span><span style="color: #000000">"</span><span style="color: #000000">Not&nbsp;closing&nbsp;pre-bound&nbsp;Hibernate&nbsp;Session&nbsp;after&nbsp;HibernateTemplate</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
</span><span style="color: #008080">32</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;disableFilters(session);<br />
</span><span style="color: #008080">33</span><span style="color: #000000"><img id="Codehighlighter1_1225_1277_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1225_1277_Open_Text.style.display='none'; Codehighlighter1_1225_1277_Closed_Image.style.display='inline'; Codehighlighter1_1225_1277_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1225_1277_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1225_1277_Closed_Text.style.display='none'; Codehighlighter1_1225_1277_Open_Image.style.display='inline'; Codehighlighter1_1225_1277_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(previousFlushMode&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">null</span><span style="color: #000000">)&nbsp;</span><span id="Codehighlighter1_1225_1277_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_1225_1277_Open_Text"><span style="color: #000000">{<br />
</span><span style="color: #008080">34</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session.setFlushMode(previousFlushMode);<br />
</span><span style="color: #008080">35</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
</span><span style="color: #008080">36</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
</span><span style="color: #008080">37</span><span style="color: #000000"><img id="Codehighlighter1_1292_1558_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1292_1558_Open_Text.style.display='none'; Codehighlighter1_1292_1558_Closed_Image.style.display='inline'; Codehighlighter1_1292_1558_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1292_1558_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1292_1558_Closed_Text.style.display='none'; Codehighlighter1_1292_1558_Open_Image.style.display='inline'; Codehighlighter1_1292_1558_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;</span><span id="Codehighlighter1_1292_1558_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_1292_1558_Open_Text"><span style="color: #000000">{<br />
</span><span style="color: #008080">38</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;Never&nbsp;use&nbsp;deferred&nbsp;close&nbsp;for&nbsp;an&nbsp;explicitly&nbsp;new&nbsp;Session.</span><span style="color: #008000"><br />
</span><span style="color: #008080">39</span><span style="color: #008000"><img id="Codehighlighter1_1390_1444_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1390_1444_Open_Text.style.display='none'; Codehighlighter1_1390_1444_Closed_Image.style.display='inline'; Codehighlighter1_1390_1444_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1390_1444_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1390_1444_Closed_Text.style.display='none'; Codehighlighter1_1390_1444_Open_Image.style.display='inline'; Codehighlighter1_1390_1444_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(isAlwaysUseNewSession())&nbsp;</span><span id="Codehighlighter1_1390_1444_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_1390_1444_Open_Text"><span style="color: #000000">{<br />
</span><span style="color: #008080">40</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SessionFactoryUtils.closeSession(session);<br />
</span><span style="color: #008080">41</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
</span><span style="color: #008080">42</span><span style="color: #000000"><img id="Codehighlighter1_1455_1553_Open_Image" onclick="this.style.display='none'; Codehighlighter1_1455_1553_Open_Text.style.display='none'; Codehighlighter1_1455_1553_Closed_Image.style.display='inline'; Codehighlighter1_1455_1553_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_1455_1553_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_1455_1553_Closed_Text.style.display='none'; Codehighlighter1_1455_1553_Open_Image.style.display='inline'; Codehighlighter1_1455_1553_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;</span><span id="Codehighlighter1_1455_1553_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_1455_1553_Open_Text"><span style="color: #000000">{<br />
</span><span style="color: #008080">43</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session,&nbsp;getSessionFactory());<br />
</span><span style="color: #008080">44</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
</span><span style="color: #008080">45</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
</span><span style="color: #008080">46</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
</span><span style="color: #008080">47</span><span style="color: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></div>
<br />
当执行到 Object result = action.doInHibernate(sessionToExpose);这部的时候，会调用相应的实现类的方法。<br />
至于为什么要这么做，在平常操作Hibernate的时候要进行一些异常处理，写一大堆try catch finally代码，这些代码跟业务逻辑毫无关联，但是还非写不可，而且这些代码在每个操作里都是一样的，这时我们就可以用一个类来封装这些操作。这样，开发人员就不<br />
必为写关注这些与业务逻辑无关的操作，在调用的时候传入实现了HibernateCallback接口的类即可。这样大大加速了开发速度。自己感兴趣的话，也可以自己实现一下。这样对设计模式的理解会更深一步的。
<img src ="http://www.blogjava.net/liuqiang5151/aggbug/192255.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuqiang5151/" target="_blank">刘强</a> 2008-04-11 18:34 <a href="http://www.blogjava.net/liuqiang5151/articles/192255.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转 Hibernate关联关系</title><link>http://www.blogjava.net/liuqiang5151/articles/144926.html</link><dc:creator>刘强</dc:creator><author>刘强</author><pubDate>Thu, 13 Sep 2007 09:44:00 GMT</pubDate><guid>http://www.blogjava.net/liuqiang5151/articles/144926.html</guid><wfw:comment>http://www.blogjava.net/liuqiang5151/comments/144926.html</wfw:comment><comments>http://www.blogjava.net/liuqiang5151/articles/144926.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liuqiang5151/comments/commentRss/144926.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liuqiang5151/services/trackbacks/144926.html</trackback:ping><description><![CDATA[<p>三张表<br />
Bookinfo (bookid, bookname, bookprice, pubulisid)<br />
Public (publishid, publishname)<br />
Auth (authid, authname, authage)</p>
<p><br />
bookinfo 和 auth 是一对一的关系， 共享主键<br />
在bookinfo中<br />
&lt;one-to-one name="auth" class="com.softeem.book.pojo.Auth" /&gt;<br />
在auth中<br />
&lt;id ....<br />
&nbsp;&nbsp;&lt;generator class="foreign"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;param name="property"&gt;info&lt;/param&gt;<br />
&nbsp;&nbsp;&lt;/generator&gt;<br />
&lt;/id&gt;<br />
&lt;one-to-one name="info" class="com.softeem.book.pojo.BookInfo" /&gt;</p>
<p>一对一， 外键关联<br />
bookinfo中不变<br />
auth中<br />
&lt;id ....<br />
&nbsp;&nbsp;&lt;generator class="uuid.hex" / &gt; 无需foreign<br />
&lt;/id&gt;<br />
&lt;many-to-one name="info" column="BOOKINFOID" class="com.softeem.book.pojo.BookInfo" <br />
&nbsp;&nbsp;unique="true" &lt;!-- 这句关键，表示唯一的多对一，也就变成一对一,而且auth表必须有BOOKINFOID这个字段 --&gt;<br />
/&gt;</p>
<p><br />
bookinfo 和 publish 是多对一的关系<br />
在bookinfo中<br />
&lt;many-to-one name="publish" column="PUBLISHID" class="com.softeem.book.pojo.Publish" &gt;<br />
&lt;/many-to-one&gt;<br />
在publish中<br />
&lt;set name="books"&gt;<br />
&nbsp;&nbsp;&lt;key column="PUBLISHID" /&gt;<br />
&nbsp;&nbsp;&lt;one-to-many class="com.softeem.book.pojo.BookInfo" /&gt;<br />
&lt;/set&gt;</p>
<p>&nbsp;<br />
在以上这种配置情况下<br />
java代码：<br />
BookInfo book = (BookInfo)session.get(BookInfo.class, "123"); //数据库有该数据， 并且有对应的publish和auth数据<br />
根据测试， bookinfo对auth的策略是预先抓取， bookinfo对publish是延迟加载<br />
由此可见，在一对一中默认是预先加载<br />
多对一中默认是延迟加载， 一对多默认是延迟加载</p>
<p><br />
现在开始试验各种配置<br />
bookinfo 对 auth<br />
&lt;one-to-one name="auth" class="com.softeem.book.pojo.Auth" lazy="proxy|no-proxy|false" /&gt;<br />
lazy每种都试了，发现都是预先抓取，将constrained设为true就变成延迟加载了,得知这里lazy的无效<br />
由于一对一默认是预先加载，若要是实现延迟加载，则需要设置constrained为true，并将一对一另一端的class设为lazy="true",<br />
在这里即是将Auth的class的lazy="true",因为lazy默认为true，可以不写<br />
&lt;one-to-one name="auth" class="com.softeem.book.pojo.Auth" constrained="true"/&gt;</p>
<p>bookinfo 对 publish, 设置lazy="false" 预先抓取，设置lazy="proxy|no-proxy", 延迟加载<br />
&lt;many-to-one name="publish" column="PUBLISHID" class="com.softeem.book.pojo.Publish" lazy="false" &gt;<br />
&lt;/many-to-one&gt;</p>
<p><br />
测试session的save方法<br />
BookInfo info = new BookInfo();<br />
info.setBookId("34534");<br />
info.setBookName("oh yeah");<br />
info.setBookPrice(12);<br />
session.save(info);<br />
若如下设置，会报异常， 将constrained设为false， 或去掉constrained属性 则可以<br />
&lt;one-to-one name="auth" class="com.softeem.book.pojo.Auth" constrained="true" /&gt;<br />
</p>
<p><br />
session的load和get方法<br />
get方法:<br />
通过id在session缓存中查找对象，未找到，则在二级缓存中查找，若未找到，则从数据库中查找(立即查找)<br />
若无对应数据,，则返回null<br />
load方法:<br />
需要分两种情况<br />
立即加载对象,如&nbsp;&lt;class name="Publish"&nbsp;table="PUBLISH" lazy="false".....&gt;<br />
同get方法一样，唯一的区别在于数据库若无对应数据，则会抛出异常。<br />
延迟加载对象，如 &lt;class name="Publish"&nbsp;table="PUBLISH" lazy="true".....&gt; (lazy默认为true)<br />
同get方法基本一样，区别在于若在二级缓存中未找到，不会立即去查数据库，而是返回一个代理对象，直到这个对象被访问时，<br />
才去查找数据库。</p>
<p><br />
对象级联操作<br />
一对一情况<br />
cascade属性<br />
cascade="none|save-update|delete|all|delete-orphan"<br />
将cascade设置为none时<br />
无法将临时对象保存到session中去，例如<br />
Publish publish = (Publish)session.get(Publish.class, "999");&nbsp; //存在记录<br />
BookInfo info = new BookInfo();//bookid 是 uuid<br />
info.setBookName("lol");<br />
info.setBookPrice("lol");<br />
publish.getBooks().add(info);<br />
将一个临时对象通过这种方式保存到session中，会报异常。</p>
<p>将cascade设置为save-update时<br />
以上代码不变，添加bookinfo成功。<br />
但有一点得说一下这个代码<br />
BookInfo book = (BookInfo)session.get(BookInfo.class, "123"); //存在记录<br />
publish.getBooks().remove(book);<br />
就算配置了save-update，这句代码并没有去删除数据库bookinfo对应的记录，而是做了update操作<br />
将这条bookinfo的记录的publishid设为null，即剥离了改条bookinfo与publish的关系。<br />
紧接上面代码接着写<br />
book.setBookName("update name"); <br />
.....//提交事务<br />
会发现数据库改条记录的bookname已经变为update name, 说明虽然剥离的与publish的关系，但它依然是一个持久化对象。</p>
<p>将cascade设置为delete-orphan时<br />
这个属性要还是用到上面的代码，当执行publish.getBooks().remove(book);后，会发现首先这个book变为脱管对象，<br />
而且数据库对应的这条记录已经被delete了。</p>
<p>将cascade设置为delete时<br />
若删除publish，则对应的bookinfo都会被删除。<br />
值得一提的, 若在publish的set里面没有设置inverse属性(默认为false)，则hibernate在执行时，会先剥离publish与其<br />
对应的所有bookinfo的关系，即update bookinfo set publishid = null where publishid=?<br />
然后再执行delete，中间这个update显得很多余，若将inverse设为true,则这句update就省了。</p>
<p>将cascade设置为all时<br />
包含save-update和delete</p>
<p>&nbsp;</p>
<p><br />
一对多，多对一情况<br />
bookinfo和publish<br />
例如，新增一个bookinfo记录<br />
可以使用"publish添加bookinfo" 或是 "bookinfo添加publish"<br />
一般思路会首先想到前者：<br />
bookinfo的many-to-one中设置cascade="none"<br />
publish的set中设置cascade="save-update"<br />
代码如下<br />
Publish publish = (Publish)session.get(Publish.class, "999");&nbsp;&nbsp;&nbsp;//存在记录<br />
BookInfo info = new BookInfo();<br />
info.setBookName("lol");<br />
info.setBookPrice(99)；<br />
publish.getBooks().add(info);<br />
Hibernate会首先查询该publish，然后查询该pubilshid对应的所有bookinfo，然后再insert该bookinfo，但此时的publishid还是null，<br />
所以后面接着一句update给publishid赋值，建立与publish的关系。<br />
若将publish的set中设置inverse="true"(inverse为true表示双方的关系交由对方维护，这里即是bookinfo)<br />
再执行以上代码，最后的insert和update会合成一句insert，但此时双方的关系由bookinfo维护，Hibernate不会再根据publish<br />
中的publishid去关联bookinfo的publishid，所以该bookinfo记录的publishid为null。<br />
需要修改代码如下<br />
Publish publish = (Publish)session.get(Publish.class, "999");&nbsp;&nbsp;&nbsp;//存在记录<br />
BookInfo info = new BookInfo();<br />
info.setBookName("lol");<br />
info.setBookPrice(99)；<br />
publish.getBooks().add(info);<br />
info.setPublish(publish);<br />
则会给publishid赋上值，但依然是查询了该publisid对应的所有bookinfo记录。</p>
<p>不如使用"bookinfo添加publish"的方式<br />
Publish publish = (Publish)session.get(Publish.class, "999");&nbsp;&nbsp;&nbsp;//存在记录<br />
BookInfo info = new BookInfo();<br />
info.setBookName("lol");<br />
info.setBookPrice(99)；<br />
info.setPublish(publish);<br />
session.save(info);<br />
Hibernate先查询该publish，然后进行insert。效率相当高</p>
<p>还有种情况，若想清除publish中对应的bookinfo集合，并赋一个新集合，<br />
BookInfo info = new BookInfo();<br />
info.setBookName("lol");<br />
info.setBookPrice(99)；<br />
Set set = new HashSet();<br />
set.add(info);<br />
Publish publish = (Publish)session.get(Publish.class, "999");&nbsp;&nbsp;&nbsp;//存在记录<br />
publish.getBooks().clear();&nbsp; //清除bookinfo集合<br />
publish.getBooks().addAll(set);<br />
info.setPublish(publish);<br />
此时publish的&lt;set cascade="save-update,delete-orphan" inverse="true"&gt;.....&lt;/set&gt;<br />
未做尝试</p>
<p><br />
多对多情况<br />
因为要描述多对多情况，将原来的表关系做一些改变，将bookinfo和auth改为多对多(本来就应该这样-_-),<br />
多对多关系必须新建一张表BOOKINFOAUTH(BOOKINFOID, AUTHID), 在hibernate中无需新建xml和po来对应<br />
那么bookinfo中原来的one-to-one注释掉<br />
&lt;set name="auths" table="BOOKINFOAUTH"&gt; &lt;!-- 这里table就对应关系表，name会在bookinfo的po中生成一个set集合的属性 --&gt;<br />
&nbsp;&nbsp;&lt;key column="BOOKINFOID" /&gt;&nbsp; &lt;!-- 这里搞了半天，这个column应该是关系表中对应bookinfo主键那个字段，即BOOKINFOID, 而不是bookinfo的主键BOOKID--&gt;<br />
&nbsp;&nbsp;&lt;many-to-many column="AUTHID" class="com.softeem.book.pojo.Auth" /&gt; <br />
&nbsp;&nbsp;&lt;!--<br />
&nbsp;&nbsp;&nbsp; 这里多对多的class就是表示当前的bookinfo与谁多对多，这里即AUTH，<br />
&nbsp;&nbsp;&nbsp; column就是关系表中对应auth主键的那个字段，而不是auth表的主键<br />
&nbsp;&nbsp;--&gt;<br />
&lt;/set&gt;&nbsp;<br />
而auth中的配置是一样的<br />
&lt;set name="bookinfos" table="BOOKINFOAUTH"&gt;<br />
&nbsp;&lt;key column="AUTHID"&gt;&lt;/key&gt;<br />
&nbsp;&lt;many-to-many column="BOOKINFOID" class="com.softeem.book.pojo.BookInfo" /&gt;&nbsp;&nbsp;&nbsp;<br />
&lt;/set&gt;<br />
添加两者间的关系，bookinfo和auth表都无需修改，只需在bookinfoauth中新增一条记录<br />
代码<br />
BookInfo info = (BookInfo)session.get(BookInfo.class, "oooooo");&nbsp; //记录存在<br />
Auth auth = (Auth)session.get(Auth.class, "123");&nbsp;&nbsp;&nbsp;//记录存在<br />
auth.getBookinfos().add(info);<br />
info.getAuths().add(auth);<br />
执行后会发现在关系表中添加了两条一样的记录，这是因为现在双方都有控制权，所以上面两句会重复insert两句一样的记录<br />
一般会将关系表的两个字段做联合主键，那这时则会报错<br />
解决的办法就是让一方释放控制权，使用inverse属性，在任一个set中设inverse为true, 即释放控制权，<br />
则只有另一方才能insert，则不会造成重复。<br />
删除关联关系<br />
BookInfo info = (BookInfo)session.get(BookInfo.class, "oooooo");<br />
Auth auth = (Auth)session.get(Auth.class, "123");<br />
auth.getBookinfos().remove(info);&nbsp; //这里我将bookinfo的set设为了inverse="true", 这会删除数据库对应的记录</p>
<p>在多对多中cascade不能设delete或all, 因为有两方面的对应关系。</p>
<p><br />
事务<br />
Hibernate自身不提供事务功能，是直接使用JDBC或JTA事务，默认是JDBC<br />
配置JTA<br />
&lt;property name="hibernate.transaction.factory_class"&gt;<br />
net.sf.hibernate.transaction.JTATransactionFactory<br />
&lt;/property&gt;<br />
&lt;!-- net.sf.hibernate.transaction.JDBCTransactionFactory --&gt;<br />
两者的不同在于<br />
JDBC:<br />
hibernateUtil.getSession()相当于JDBC的Connection.getConnection()<br />
session.beginTransaction()相当于JDBC的conn.setAuto(false) //因为JDBC默认是自动提交模式，即每一个sql语句执行后事务将被提交，<br />
而后一个新的事务又开始了。<br />
tx.commit()相当于JDBC的conn.commit()<br />
session.close()相当于JDBC的conn.close();<br />
以上是JDBC的模式，可以看出先创建session，再获得事务(transaction), 即事务从session中获得。事务提交必须关闭session。<br />
而JTA的模式是先获得事务，再启动session，关闭session，提交事务。<br />
因此JTA的事务生命周期长于session，所以JTA一般用来管理跨session的长事务，分布式的数据库等</p>
<p>事务隔离级别：<br />
隔离级别&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 是否出现第一类丢失更新&nbsp;&nbsp; 是否出现脏读&nbsp;&nbsp; 是否出现虚读&nbsp;&nbsp; 是否出现不可重复读&nbsp;&nbsp; 是否出现第二类丢失更新<br />
1:读操作未提交(Read Uncommited)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 是&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 是&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 是&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 是<br />
2:读操作已提交(Read Commited)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 是&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 是&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 是<br />
4:可重复读(Repeatable Read)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 是&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 否<br />
8:可串行化(Serializable)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 否</p>
<p>第一类更新丢失：后发生的事务回滚覆盖了前面提交成功的事务<br />
脏读：后发生的事务成功提交覆盖了前面的回滚的事务<br />
虚读：后一个事务在前后两次读取数据时由于前面的已提交的事务进行了插入操作，而使数据统计前后不一致。<br />
不可重复读：后一个事务在对同一条数据前后两次读取时由于前面的已提交的事务进行了对这条数据更新操作，而使数据前后不一致。<br />
第二类更新丢失：后发生的事务成功提交覆盖了前面的成功提交的事务</p>
<p>读操作未提交显然太不安全。可串行化又过于安全，影响并发性能，性价比最好的是读操作已提交。</p>
<p>在hibernate中设置<br />
&lt;property name="hibernate.connection.isolation"&gt;4&lt;/property&gt;<br />
这是全局性的配置</p>
<p><br />
事务功能靠的是锁(lock)<br />
分为乐观锁和悲观锁<br />
悲观锁悲观地认为每次资料存取时，其他的客户端也会取同一笔数据。<br />
当一个事务开始直到结束，这把锁会禁止其他进程对它所保护的数据进行修改(只读)。<br />
一般数据库不采用这种方式，性能太差，使用方式<br />
Transaction tx = session.beginTransaction();<br />
BookInfo info = (BookInfo)session.get(BookInfo.class, "oooooo", LockMode.UPGRADE);&nbsp;<br />
info.setBookPrice(info.getBookPrice() + 1);<br />
session.update(info);<br />
tx.commit();<br />
在通过session.get()方式查找这个记录时的sql语句是这样的<br />
select ........ from BOOKINFO bookinfo0_ where bookinfo0_.BOOKID=? for update<br />
会在后面加个for update 即是悲观锁，也就查找到后直到事务结束，记录都会被锁，处于只读状态<br />
LockMode.UPGRADE:不管Hibernate的缓存中是否存在指定对象，总是通过select语句到数据库中加载该对象；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果映射文件中设置了版本元素，就执行版本检查，比较缓存中的指定对象是否和数据库中的版本一致。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果数据库系统支持悲观锁就执行select。。。for update语句，如果数据库系统不支持悲观锁，就执行普通的select语句。<br />
LockMode.UPDGRADE_NOWWAIT:是利用oracle的for update nowait 子句加锁<br />
Hibernate加锁的三种方式：Query&nbsp; Criteria&nbsp; Session<br />
Hibernate还有三种内部加锁模式:<br />
LockMode.NONE：无锁机制。&nbsp;&nbsp;&nbsp; <br />
LockMode.READ：不管Hibernate的缓存中是否存在指定对象，总是通过select语句到数据库中加载该对象；<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果映射文件中设置了版本元素，就执行版本检查，比较缓存中的指定对象是否和数据库中的版本一致。&nbsp; <br />
LockMode.WRITE：当Hibernate向数据库保存或者更新一个对象时，会自动使用此模式。<br />
在程序中不能指定内部模式<br />
session.get() session.load() 默认是LockMode.NONE</p>
<p>乐观锁乐观地认为资料的存取很少发生同时存取的问题,所以不作数据库层次上的锁定，而是使用应用程序上的逻辑实现版本控制解决<br />
在不实行悲观锁策略下，数据不一致一旦发生，一种采用先更新为主，一种采用后更新为主，比较复杂的是检查发生变动的数据来实现<br />
默认是以后更新为主。</p>
<p>复杂的方式：<br />
1.使用版本检查<br />
Hibernate通过版本号检查来实现后更新为主，在数据库中加入一个version字段记录，在读取数据库连同版本号一同读取，并在更新时<br />
比较版本号与数据库中的版本号。<br />
在bookinfo里加个version字段，类型为number，初始值为0<br />
在配置里<br />
&lt;class name="BookInfo" table="BOOKINFO"&nbsp;lazy="true" optimistic-lock="version"&gt;<br />
紧接id后面配置&lt;version name="version" column="VERSION" type="integer" /&gt;<br />
那么在事务提交更新数据库时会检查版本号，若版本号一样则更新，若不一样则抛出异常。<br />
问题：无法防止人为的修改版本号行为<br />
2.使用时间戳<br />
与版本检查原理一样，加个字段LASTUPDATEDTIME,类型为Date。<br />
配置里<br />
&lt;class name="BookInfo" table="BOOKINFO"&nbsp;lazy="true" optimistic-lock="version"&gt;<br />
紧接id后面配置&lt;timestamp name="lastudpateTime" column="LASTUPDATEDTIME" /&gt;&nbsp;&nbsp;<br />
优点：Hibernate会自动根据当前时间更新时间戳。<br />
但稍微不安全，若在同一个毫秒级别上并发，则版本检查会无法判断。</p>
<p><br />
Oracl对Blob和Clob的处理<br />
以publish举例，descip为clob字段， photo为blob字段<br />
说明：因为在Oracce中Blob/Clob字段独特的访问方式，Oracle Blob/Clob字段本身拥有一个游标(cursor) , <br />
JDBC必须通过游标对Blob/ Clob字段进行操作，在Blob/Clob字段被创建之前，我们无法获取其游标句柄，<br />
这也就意味着，我们必须首先创建一个空Blob/Clob字段，再从这个空Blob/Clob字段获取游标，<br />
写入我们所期望保存的数据。 <br />
例子<br />
Clob:<br />
写操作<br />
Publish publish = new Publish();<br />
publish.setPublishid("333");<br />
publish.setPublishname("000000");<br />
publish.setDescip(Hibernate.createClob(" "));&nbsp;&nbsp;//这里必须先写个空字符的字符串<br />
session.save(publish);&nbsp;<br />
tx.commit();<br />
--------------<br />
Publish pub = (Publish)session.get(Publish.class, "333", LockMode.UPGRADE); <br />
//这里必须用悲观锁 锁定 ，否则会报"未锁定含有 LOB 值的行"<br />
SerializableClob cl = (SerializableClob)pub.getDescip();<br />
CLOB clob= (CLOB)cl.getWrappedClob();<br />
Writer write = clob.getCharacterOutputStream();<br />
write.write(str.toString());<br />
write.flush();<br />
write.close();<br />
session.saveOrUpdate(pub);<br />
tx.commit();</p>
<p>读操作<br />
Publish publish = (Publish)session.get(Publish.class, "333");<br />
Reader in = publish.getDescip().getCharacterStream();<br />
BufferedReader reader = new BufferedReader(in);<br />
StringBuffer sb = new StringBuffer();<br />
while ((str = reader.readLine()) != null){<br />
&nbsp;&nbsp;sb.append(str);<br />
}<br />
System.out.println(sb.toString());</p>
<p>Blob:<br />
写操作<br />
Publish publish = new Publish();<br />
publish.setPublishid("555");<br />
publish.setPublishname("000000");<br />
publish.setPhoto(Hibernate.createBlob(new byte[1]));&nbsp;&nbsp;//这里必须先写个空字节<br />
session.save(publish);&nbsp;<br />
tx.commit();<br />
--------------<br />
Publish publish = (Publish)session.get(Publish.class, "555", LockMode.UPGRADE); <br />
//这里一样必须用悲观锁 锁定 ，否则会报"未锁定含有 LOB 值的行"<br />
SerializableBlob sb = (SerializableBlob)publish.getPhoto();<br />
BLOB blob = (BLOB)sb.getWrappedBlob();<br />
OutputStream out = blob.getBinaryOutputStream();<br />
FileInputStream file = new FileInputStream("D:\\11.jpg");<br />
byte[] bt = new byte[10240];<br />
int len;<br />
while((len = file.read(bt)) != -1){ <br />
&nbsp;&nbsp; out.write(bt,0,len); <br />
} <br />
out.flush();<br />
file.close();<br />
out.close();</p>
<p>读操作<br />
Publish publish = (Publish)session.get(Publish.class, "555");<br />
InputStream in = publish.getPhoto().getBinaryStream();<br />
FileOutputStream out = new FileOutputStream("d:\\44.jpg");<br />
byte[] buf = new byte[10240];<br />
int len;<br />
while ((len = in.read(buf)) != -1){<br />
&nbsp;&nbsp;&nbsp;out.write(buf, 0, len);<br />
}<br />
in.close();<br />
out.close();<br />
</p>
<img src ="http://www.blogjava.net/liuqiang5151/aggbug/144926.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuqiang5151/" target="_blank">刘强</a> 2007-09-13 17:44 <a href="http://www.blogjava.net/liuqiang5151/articles/144926.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转 Hibernate各种保存方式的区别</title><link>http://www.blogjava.net/liuqiang5151/articles/144924.html</link><dc:creator>刘强</dc:creator><author>刘强</author><pubDate>Thu, 13 Sep 2007 09:39:00 GMT</pubDate><guid>http://www.blogjava.net/liuqiang5151/articles/144924.html</guid><wfw:comment>http://www.blogjava.net/liuqiang5151/comments/144924.html</wfw:comment><comments>http://www.blogjava.net/liuqiang5151/articles/144924.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/liuqiang5151/comments/commentRss/144924.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/liuqiang5151/services/trackbacks/144924.html</trackback:ping><description><![CDATA[<p>hibernate的保存<br />
hibernate对于对象的保存提供了太多的方法，他们之间有很多不同，这里细说一下，以便区别：<br />
一、预备知识：<br />
在所有之前，说明一下，对于hibernate，它的对象有三种状态，transient、persistent、detached<br />
下边是常见的翻译办法：<br />
transient：瞬态或者自由态<br />
persistent：持久化状态<br />
detached：脱管状态或者游离态</p>
<p>脱管状态的实例可以通过调用save()、persist()或者saveOrUpdate()方法进行持久化。<br />
持久化实例可以通过调用 delete()变成脱管状态。通过get()或load()方法得到的实例都是持久化状态的。<br />
脱管状态的实例可以通过调用 update()、0saveOrUpdate()、lock()或者replicate()进行持久化。</p>
<p>save()和persist()将会引发SQL的INSERT，delete()会引发SQLDELETE，<br />
而update()或merge()会引发SQLUPDATE。对持久化（persistent）实例的修改在刷新提交的时候会被检测到，<br />
它也会引起SQLUPDATE。saveOrUpdate()或者replicate()会引发SQLINSERT或者UPDATE</p>
<p>二、save 和update区别<br />
把这一对放在第一位的原因是因为这一对是最常用的。<br />
save的作用是把一个新的对象保存<br />
update是把一个脱管状态的对象保存</p>
<p>三,update 和saveOrUpdate区别<br />
这个是比较好理解的，顾名思义，saveOrUpdate基本上就是合成了save和update<br />
引用hibernate reference中的一段话来解释他们的使用场合和区别<br />
通常下面的场景会使用update()或saveOrUpdate()： <br />
程序在第一个session中加载对象 <br />
该对象被传递到表现层 <br />
对象发生了一些改动 <br />
该对象被返回到业务逻辑层 <br />
程序调用第二个session的update()方法持久这些改动 </p>
<p>saveOrUpdate()做下面的事: <br />
如果对象已经在本session中持久化了，不做任何事 <br />
如果另一个与本session关联的对象拥有相同的持久化标识(identifier)，抛出一个异常 <br />
如果对象没有持久化标识(identifier)属性，对其调用save() <br />
如果对象的持久标识(identifier)表明其是一个新实例化的对象，对其调用save() <br />
如果对象是附带版本信息的（通过&lt;version&gt;或&lt;timestamp&gt;） 并且版本属性的值表明其是一个新实例化的对象，save()它。 <br />
否则update() 这个对象 </p>
<p>四,persist和save区别<br />
这个是最迷离的一对，表面上看起来使用哪个都行，在hibernate reference文档中也没有明确的区分他们.<br />
这里给出一个明确的区分。（可以跟进src看一下，虽然实现步骤类似，但是还是有细微的差别）<br />
这里参考<a href="http://opensource.atlassian.com/projects/hibernate/browse/HHH-1682">http://opensource.atlassian.com/projects/hibernate/browse/HHH-1682</a>中的一个说明：<br />
---------------------------------------------------------------------------------<br />
I found that a lot of people have the same doubt. To help to solve this issue <br />
I'm quoting Christian Bauer:<br />
"In case anybody finds this thread...</p>
<p>persist() is well defined. It makes a transient instance persistent. However, <br />
it doesn't guarantee that the identifier value will be assigned to the persistent <br />
instance immediately, the assignment might happen at flush time. The spec doesn't say <br />
that, which is the problem I have with persist().</p>
<p>persist() also guarantees that it will not execute an INSERT statement if it is <br />
called outside of transaction boundaries. This is useful in long-running conversations <br />
with an extended Session/persistence context.A method like persist() is required.</p>
<p>save() does not guarantee the same, it returns an identifier, and if an INSERT <br />
has to be executed to get the identifier (e.g. "identity" generator, not "sequence"), <br />
this INSERT happens immediately, no matter if you are inside or outside of a transaction. This is not good in a long-running conversation with an extended Session/persistence context."</p>
<p>---------------------------------------------------------------------------------<br />
简单翻译一下上边的句子的主要内容：<br />
1，persist把一个瞬态的实例持久化，但是并"不保证"标识符被立刻填入到持久化实例中，标识符的填入可能被推迟<br />
到flush的时间。</p>
<p>2，persist"保证"，当它在一个transaction外部被调用的时候并不触发一个Sql Insert，这个功能是很有用的，<br />
当我们通过继承Session/persistence context来封装一个长会话流程的时候，一个persist这样的函数是需要的。</p>
<p>3，save"不保证"第2条,它要返回标识符，所以它会立即执行Sql insert，不管是不是在transaction内部还是外部</p>
<p><br />
五,saveOrUpdateCopy,merge和update区别<br />
首先说明merge是用来代替saveOrUpdateCopy的，这个详细见这里<br />
<a href="http://www.blogjava.net/dreamstone/archive/2007/07/28/133053.html">http://www.blogjava.net/dreamstone/archive/2007/07/28/133053.html</a><br />
然后比较update和merge<br />
update的作用上边说了，这里说一下merge的<br />
如果session中存在相同持久化标识(identifier)的实例，用用户给出的对象的状态覆盖旧有的持久实例 <br />
如果session没有相应的持久实例，则尝试从数据库中加载，或创建新的持久化实例,最后返回该持久实例 <br />
用户给出的这个对象没有被关联到session上，它依旧是脱管的 <br />
重点是最后一句：<br />
当我们使用update的时候，执行完成后，我们提供的对象A的状态变成持久化状态<br />
但当我们使用merge的时候，执行完成，我们提供的对象A还是脱管状态，hibernate或者new了一个B，或者检索到<br />
一个持久对象B，并把我们提供的对象A的所有的值拷贝到这个B，执行完成后B是持久状态，而我们提供的A还是托管状态</p>
<p>六,flush和update区别<br />
这两个的区别好理解<br />
update操作的是在脱管状态的对象<br />
而flush是操作的在持久状态的对象。<br />
默认情况下，一个持久状态的对象是不需要update的，只要你更改了对象的值，等待hibernate flush就自动<br />
保存到数据库了。hibernate flush发生再几种情况下：<br />
1，调用某些查询的时候<br />
2，transaction commit的时候<br />
3，手动调用flush的时候 </p>
<p>七,lock和update区别<br />
update是把一个已经更改过的脱管状态的对象变成持久状态<br />
lock是把一个没有更改过的脱管状态的对象变成持久状态<br />
对应更改一个记录的内容，两个的操作不同：<br />
update的操作步骤是：<br />
（1）更改脱管的对象-&gt;调用update<br />
lock的操作步骤是：<br />
(2)调用lock把对象从脱管状态变成持久状态--&gt;更改持久状态的对象的内容--&gt;等待flush或者手动flush</p>
<p>参考内容：<br />
<a href="http://www.blogjava.net/iamtin/archive/2006/03/06/33910.aspx">http://www.blogjava.net/iamtin/archive/2006/03/06/33910.aspx</a><br />
<a href="http://opensource.atlassian.com/projects/hibernate/browse/HHH-1682">http://opensource.atlassian.com/projects/hibernate/browse/HHH-1682</a><br />
<a href="http://www.redsaga.com/hibernate-ref/3.x/zh-cn/html/objectstate.html">http://www.redsaga.com/hibernate-ref/3.x/zh-cn/html/objectstate.html</a></p>
<img src ="http://www.blogjava.net/liuqiang5151/aggbug/144924.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/liuqiang5151/" target="_blank">刘强</a> 2007-09-13 17:39 <a href="http://www.blogjava.net/liuqiang5151/articles/144924.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>