<p>1)與Java對(duì)象在JVM中的生命周期類似,Java對(duì)象在Hibernate的session中也有生命周期類似的狀態(tài)。在Hibernate的session中,對(duì)象有3種狀態(tài):臨時(shí)狀態(tài),持久化狀態(tài),游離狀態(tài)。<br />
a. 臨時(shí)狀態(tài)(transient),剛new出來的對(duì)象,還沒有被session持久化,不處于session的緩存中<br />
b.持久化狀態(tài)(persistent),已經(jīng)被持久化(在數(shù)據(jù)庫中有相應(yīng)的記錄),并且存在于session的緩存中<br />
c. 游離狀態(tài)(detached),已經(jīng)被持久化(在數(shù)據(jù)庫中可能存在也可能不存在相應(yīng)的記錄),不存在于session的緩存中<br />
<br />
簡單的用個(gè)例子描述一下:<br />
</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"><span style="color: #008080"> 1</span><img alt="" src="/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000"><img alt="" src="http://www.aygfsteel.com/Images/dot.gif" /><br />
</span><span style="color: #008080"> 2</span><span style="color: #000000"><img alt="" src="/Images/OutliningIndicators/None.gif" align="top" />tx </span><span style="color: #000000">=</span><span style="color: #000000"> session.beginTransaction();<br />
</span><span style="color: #008080"> 3</span><span style="color: #000000"><img alt="" src="/Images/OutliningIndicators/None.gif" align="top" />Customer c1 </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">new</span><span style="color: #000000"> Customer(</span><span style="color: #000000">"</span><span style="color: #000000">Tom</span><span style="color: #000000">"</span><span style="color: #000000">,</span><span style="color: #0000ff">new</span><span style="color: #000000"> HashSet()); //c1 處于臨時(shí)狀態(tài)<br />
</span><span style="color: #008080"> 4</span><span style="color: #000000"><img alt="" src="/Images/OutliningIndicators/None.gif" align="top" />session.save(c1); //c1轉(zhuǎn)換為持久化狀態(tài)<br />
</span><span style="color: #008080"> 5</span><span style="color: #000000"><img alt="" src="/Images/OutliningIndicators/None.gif" align="top" />Long id </span><span style="color: #000000">=</span><span style="color: #000000"> c1.getId();<br />
</span><span style="color: #008080"> 6</span><span style="color: #000000"><img alt="" src="/Images/OutliningIndicators/None.gif" align="top" />c1 </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">null</span><span style="color: #000000">;<br />
</span><span style="color: #008080"> 7</span><span style="color: #000000"><img alt="" src="/Images/OutliningIndicators/None.gif" align="top" />Customer c2 </span><span style="color: #000000">=</span><span style="color: #000000"> (Customer)session.load(Customer.</span><span style="color: #0000ff">class</span><span style="color: #000000">,id); //c2 處于持久化狀態(tài)<br />
</span><span style="color: #008080"> 8</span><span style="color: #000000"><img alt="" src="/Images/OutliningIndicators/None.gif" align="top" />tx.commit();<br />
</span><span style="color: #008080"> 9</span><span style="color: #000000"><img alt="" src="/Images/OutliningIndicators/None.gif" align="top" />session.close(); //c1轉(zhuǎn)換為游離狀態(tài) <br />
</span><span style="color: #008080">10</span><span style="color: #000000"><img alt="" src="/Images/OutliningIndicators/None.gif" align="top" />c2 </span><span style="color: #000000">=</span><span style="color: #000000"> </span><span style="color: #0000ff">null</span><span style="color: #000000">; //c2轉(zhuǎn)換為游離狀態(tài)</span></div>
<br />
<br />
<br />
2)對(duì)象的狀態(tài)轉(zhuǎn)換<br />
<img height="277" alt="" src="/images/blogjava_net/ericzhang5231/StateTransform.jpg" width="398" border="0" /><br />
<br />
<table style="width: 1000px; height: 195px" cellspacing="2" cellpadding="2" width="1000" border="0">
<tbody>
<tr>
<td>狀態(tài)名稱</td>
<td>狀態(tài)特征</td>
<td>進(jìn)入條件</td>
<td>備注</td>
</tr>
<tr>
<td>臨時(shí)對(duì)象</td>
<td>
<p>1.不存在任何一個(gè)session;</p>
<p>2.在數(shù)據(jù)庫沒有相應(yīng)的記錄;</p>
</td>
<td>
<p>1. 通過new;</p>
<p>2.Session通過delete()把持久化對(duì)象和游離對(duì)象轉(zhuǎn)化為臨時(shí)對(duì)象</p>
</td>
<td></td>
</tr>
<tr>
<td>持久化對(duì)象</td>
<td>
<p>1.總是被一個(gè)Session對(duì)象關(guān)聯(lián);</p>
<p>2.在數(shù)據(jù)庫有相應(yīng)的記錄;<br />
3.session清理緩存的時(shí)候,會(huì)根據(jù)持久化對(duì)象的屬性變化(其實(shí)根據(jù)快照),來同步更新數(shù)據(jù)庫</p>
</td>
<td>
<p>1.session的save()把臨時(shí)對(duì)象轉(zhuǎn)化持久化對(duì)象;<br />
2.session的load()或get()返回的對(duì)象;<br />
3.session的find()返回的對(duì)象;<br />
4.session的update(),saveOrUpdate()和lock()使游離對(duì)象轉(zhuǎn)變?yōu)槌志没瘜?duì)象;<br />
5.當(dāng)一個(gè)持久化對(duì)象關(guān)聯(lián)一個(gè)臨時(shí)對(duì)象,當(dāng)允許級(jí)聯(lián)保存的情況下,臨時(shí)對(duì)象也轉(zhuǎn)化為持久化對(duì)象;</p>
<p> </p>
</td>
<td>1.避免多個(gè)session實(shí)例關(guān)聯(lián)一個(gè)Java對(duì)象</td>
</tr>
<tr>
<td>游離對(duì)象 </td>
<td>
<p>1.不被session關(guān)聯(lián);</p>
<p>2.游離對(duì)象是由持久化對(duì)象轉(zhuǎn)化過來的,數(shù)據(jù)庫中可能存在也可能不存在相應(yīng)的記錄;</p>
</td>
<td>
<p>1.session的close(),把緩存中的所有持久化對(duì)象都轉(zhuǎn)變?yōu)橛坞x對(duì)象;</p>
<p>2.session的evict(),把緩存中的一個(gè)持久化對(duì)象刪除,使它變成游離狀態(tài);</p>
</td>
<td>1.游離對(duì)象和臨時(shí)對(duì)象的區(qū)別在于數(shù)據(jù)庫是否存在相應(yīng)的記錄</td>
</tr>
</tbody>
</table>
<br />
<br />
<br />
3)Session的緩存以及API<br />
1.Session:在Session接口的實(shí)現(xiàn)類SessionImpl中定義了一系列的Java集合,這些集合構(gòu)成了Sessiond緩存<br />
2.API:<br />
<table style="width: 1005px; height: 270px" cellspacing="2" cellpadding="2" width="1005" border="0">
<tbody>
<tr>
<td>save()</td>
<td>
<p>1.在save一個(gè)臨時(shí)對(duì)象之前,設(shè)置對(duì)象的主鍵ID,沒效果;</p>
<p>2.在save一個(gè)對(duì)象之后,對(duì)象主鍵ID不能修改,否則拋異常;<br />
3.如果主鍵ID是用nactive方式生成的,一旦調(diào)用session的save方法,hibernate會(huì)立即向數(shù)據(jù)庫插入數(shù)據(jù);<br />
4.save用來持久化一個(gè)臨時(shí)對(duì)象,若持久一個(gè)持久化對(duì)象,沒效果,若持久一個(gè)游離對(duì)象,會(huì)重新插入數(shù)據(jù);</p>
</td>
</tr>
<tr>
<td>update()</td>
<td>
<p>1.session清理緩存的時(shí)候,才會(huì)去執(zhí)行update()產(chǎn)生的sql語句,因此即使程序多次修改對(duì)象屬性,最后只會(huì)更新最后的修改;</p>
<p>2.通過update()使一個(gè)游離對(duì)象被一個(gè)session關(guān)聯(lián),即使沒有修改對(duì)象屬性,在清理緩存的時(shí)候也會(huì)執(zhí)行update()產(chǎn)生sql語句<br />
(如果希望僅當(dāng)修改對(duì)象屬性才進(jìn)行update,可在<class>元素的select-before-update設(shè)置為true);<br />
3.當(dāng)update()方法關(guān)聯(lián)一個(gè)游離對(duì)象,如果session中存在相同OID的持久化對(duì)象,會(huì)拋出異常;<br />
4.當(dāng)update()方法關(guān)聯(lián)一個(gè)游離對(duì)象,如果數(shù)據(jù)庫中不存在相應(yīng)記錄,會(huì)拋出異常;</p>
</td>
</tr>
<tr>
<td>saveOrUpdate()</td>
<td>
<p>1.如果傳入的是臨時(shí)對(duì)象,調(diào)用save(); 如果傳入的是持久化對(duì)象,調(diào)用update();</p>
</td>
</tr>
<tr>
<td>load(), get()</td>
<td>1.兩者都是根據(jù)OID從數(shù)據(jù)庫中加載持久化對(duì)象,區(qū)別是:當(dāng)數(shù)據(jù)庫不存在與OID對(duì)應(yīng)的記錄,load()會(huì)拋出net.sf.hibernate.ObjectNotFoundException,而get()方法返回null;</td>
</tr>
<tr>
<td>delete()</td>
<td>1.對(duì)傳入的是持久化對(duì)象,session就按照預(yù)先的sql語句刪除一個(gè)記錄;如果是一個(gè)游離態(tài)對(duì)象,會(huì)把它關(guān)聯(lián)到session,在按照sql語句刪除記錄</td>
</tr>
</tbody>
</table>
<br />
3.session的級(jí)聯(lián):因?yàn)閷?duì)象是相互關(guān)聯(lián),因此在session存放的是一副相互關(guān)聯(lián)的對(duì)象圖。在對(duì)象-關(guān)聯(lián)映射文件中,用于映射持久化類之間關(guān)聯(lián)的元素,如<set>,<many-to-one>,<one-to-many>,都有一個(gè)cascade屬性。casecade屬性值如下:<br />
<table cellspacing="2" cellpadding="2" width="500" border="0">
<tbody>
<tr>
<td>屬性值</td>
<td>描述</td>
</tr>
<tr>
<td>none</td>
<td>默認(rèn)值,忽略關(guān)聯(lián)對(duì)象</td>
</tr>
<tr>
<td>save-update</td>
<td>session對(duì)當(dāng)前對(duì)象調(diào)用save(),update(),saveOrUpdate(),級(jí)聯(lián)保存關(guān)聯(lián)的臨時(shí)對(duì)象,級(jí)聯(lián)更新關(guān)聯(lián)的游離對(duì)象</td>
</tr>
<tr>
<td>delete</td>
<td>級(jí)聯(lián)刪除所有關(guān)聯(lián)的對(duì)象</td>
</tr>
<tr>
<td>all</td>
<td>包含save-update(),delelte()行為;當(dāng)對(duì)當(dāng)前對(duì)象執(zhí)行evict()或lock(),級(jí)聯(lián)執(zhí)行關(guān)聯(lián)的對(duì)象</td>
</tr>
<tr>
<td>delete-orphan</td>
<td>刪除所有和當(dāng)前對(duì)象解除關(guān)聯(lián)關(guān)系的對(duì)象</td>
</tr>
<tr>
<td>all-delete-orphan</td>
<td>包含all和delete-orphan的行為</td>
</tr>
</tbody>
</table>