﻿<?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-minghui-文章分类-Hibernate</title><link>http://www.blogjava.net/minghui/category/24673.html</link><description /><language>zh-cn</language><lastBuildDate>Sun, 12 Aug 2007 19:51:56 GMT</lastBuildDate><pubDate>Sun, 12 Aug 2007 19:51:56 GMT</pubDate><ttl>60</ttl><item><title>浅谈对象在Hibernate中的状态</title><link>http://www.blogjava.net/minghui/articles/134800.html</link><dc:creator>星海拾贝</dc:creator><author>星海拾贝</author><pubDate>Mon, 06 Aug 2007 14:15:00 GMT</pubDate><guid>http://www.blogjava.net/minghui/articles/134800.html</guid><wfw:comment>http://www.blogjava.net/minghui/comments/134800.html</wfw:comment><comments>http://www.blogjava.net/minghui/articles/134800.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/minghui/comments/commentRss/134800.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/minghui/services/trackbacks/134800.html</trackback:ping><description><![CDATA[Hibernate中的对象有三种状态：<font size=3><span lang=EN-US><span><span Times New Roman????> </span></span></span><span style="FONT-FAMILY: 宋体">瞬时状态</span></font><span lang=EN-US>(Transient)，<span style="FONT-SIZE: 10.5pt; FONT-FAMILY: 宋体"><font size=3>持久状态</font></span><span lang=EN-US style="FONT-SIZE: 10.5pt; FONT-FAMILY: " Times New Roman????><font size=3>(Persistent)，</font>
<p style="TEXT-INDENT: -18pt"><font size=3><span lang=EN-US><span>1．<span Times New Roman????> </span></span></span><span style="FONT-FAMILY: 宋体">脱管状态</span><span lang=EN-US>(Detached)</span></font></p>
</span></span><br>
<p style="TEXT-INDENT: -18pt"><span lang=EN-US><span>1．<span Times New Roman????><font size=3> １．</font></span></span></span><span style="FONT-FAMILY: 宋体">瞬时状态</span><span lang=EN-US>(Transient)</span></p>
<p><span style="FONT-FAMILY: 宋体">由</span><span lang=EN-US>new</span><span style="FONT-FAMILY: 宋体">命令开辟内存空间的</span><span lang=EN-US>Java</span><span style="FONT-FAMILY: 宋体">对象，也就是平时所熟悉的普通</span><span lang=EN-US>Java</span><span style="FONT-FAMILY: 宋体">对象。</span></p>
<p><span style="FONT-FAMILY: 宋体">如：</span><span lang=EN-US>Student stu = new Student();</span></p>
<p>
<p><span style="FONT-FAMILY: 宋体">瞬时对象特点：</span></p>
<p><span lang=EN-US>(1)</span><span style="FONT-FAMILY: 宋体">不和</span><span lang=EN-US>Session</span><span style="FONT-FAMILY: 宋体">实例关联</span><span lang=EN-US> </span></p>
<p><span lang=EN-US>(2)</span><span style="FONT-FAMILY: 宋体">在数据库中没有和瞬时对象关联的记录</span></p>
<p>
<p style="TEXT-INDENT: -18pt"><span lang=EN-US><span>2．<span Times New Roman????><font size=3> ２．</font></span></span></span><span style="FONT-FAMILY: 宋体">持久状态</span><span lang=EN-US>(Persistent)</span></p>
<p><span style="FONT-FAMILY: 宋体">持久的实例在数据库中有对应的记录，并拥有一个持久化标识</span><span lang=EN-US>(identifier).</span></p>
<p><span style="FONT-FAMILY: 宋体">持久对象总是与</span><span lang=EN-US>Session</span><span style="FONT-FAMILY: 宋体">和</span><span lang=EN-US>Transaction</span><span style="FONT-FAMILY: 宋体">相关联，在一个</span><span lang=EN-US>Session</span><span style="FONT-FAMILY: 宋体">中，对持久对象的改变不会马上对数据库进行变更，而必须在</span><span lang=EN-US>Transaction</span><span style="FONT-FAMILY: 宋体">终止，也就是执行</span><span lang=EN-US>commit()</span><span style="FONT-FAMILY: 宋体">之后，才在数据库中真正运行</span><span lang=EN-US>SQL</span><span style="FONT-FAMILY: 宋体">进行变更，持久对象的状态才会与数据库进行同步。在同步之前的持久对象称为脏</span><span lang=EN-US>(dirty)</span><span style="FONT-FAMILY: 宋体">对象。</span></p>
<p>
<p><span style="FONT-FAMILY: 宋体">瞬时对象转为持久对象：</span></p>
<p style="TEXT-INDENT: -18pt"><span lang=EN-US><span>(1)<span Times New Roman????><font size=3> </font></span></span></span><span style="FONT-FAMILY: 宋体">通过</span><span lang=EN-US>Session</span><span style="FONT-FAMILY: 宋体">的</span><span lang=EN-US>save()</span><span style="FONT-FAMILY: 宋体">和</span><span lang=EN-US>saveOrUpdate()</span><span style="FONT-FAMILY: 宋体">方法把一个瞬时对象与数据库相关联，这个瞬时对象就成为持久化对象。</span></p>
<p style="TEXT-INDENT: -18pt"><span lang=EN-US><span>(2)<span Times New Roman????><font size=3> </font></span></span></span><span style="FONT-FAMILY: 宋体">使用</span><span lang=EN-US>fine(),get(),load()</span><span style="FONT-FAMILY: 宋体">和</span><span lang=EN-US>iterater()</span><span style="FONT-FAMILY: 宋体">待方法查询到的数据对象，将成为持久化对象。</span></p>
<p>
<p><span style="FONT-FAMILY: 宋体">持久化对象的特点：</span></p>
<p style="TEXT-INDENT: -18pt"><span lang=EN-US><span>(1)<span Times New Roman????><font size=3> </font></span></span></span><span style="FONT-FAMILY: 宋体">和</span><span lang=EN-US>Session</span><span style="FONT-FAMILY: 宋体">实例关联</span></p>
<p style="TEXT-INDENT: -18pt"><span lang=EN-US><span>(2)<span Times New Roman????><font size=3> </font></span></span></span><span style="FONT-FAMILY: 宋体">在数据库中有和持久对象关联的记录</span></p>
<p>
<p style="TEXT-INDENT: -18pt"><span lang=EN-US><span>3．<span Times New Roman????><font size=3> ３．</font></span></span></span><span style="FONT-FAMILY: 宋体">脱管状态</span><span lang=EN-US>(Detached)</span></p>
<p><span style="FONT-FAMILY: 宋体">与持久对象关联的</span><span lang=EN-US>Session</span><span style="FONT-FAMILY: 宋体">被关闭后，对象就变为脱管对象。对脱管对象的引用依然有效，对象可继续被修改。</span></p>
<p>
<p><span style="FONT-FAMILY: 宋体">脱管对象特点：</span></p>
<p style="TEXT-INDENT: -18pt"><span lang=EN-US><span>(1)<span Times New Roman????><font size=3> </font></span></span></span><span style="FONT-FAMILY: 宋体">本质上和瞬时对象相同</span></p>
<p style="TEXT-INDENT: -18pt"><span lang=EN-US><span>(2)<span Times New Roman????><font size=3> </font></span></span></span><span style="FONT-FAMILY: 宋体">只是比爱瞬时对象多了一个数据库记录标识值</span><span lang=EN-US>id.</span></p>
<p>
<p><span style="FONT-FAMILY: 宋体">持久对象转为脱管对象：</span></p>
<p><span style="FONT-FAMILY: 宋体">当执行</span><span lang=EN-US>close()</span><span style="FONT-FAMILY: 宋体">或</span><span lang=EN-US>clear(),evict()</span><span style="FONT-FAMILY: 宋体">之后，持久对象会变为脱管对象。</span></p>
<p>
<p><span style="FONT-FAMILY: 宋体">瞬时对象转为持久对象：</span></p>
<p><span style="FONT-FAMILY: 宋体">通过</span><span lang=EN-US>Session</span><span style="FONT-FAMILY: 宋体">的</span><span lang=EN-US>update(),saveOrUpdate()</span><span style="FONT-FAMILY: 宋体">和</span><span lang=EN-US>lock()</span><span style="FONT-FAMILY: 宋体">等方法，把脱管对象变为持久对象。</span></p>
<p>
<p style="TEXT-INDENT: 15.75pt"><span style="FONT-FAMILY: 宋体">三种状态相互转化的状态图如下：</span></p>
<p>
<p>
<p>
<p>
<p>
<p>
<p>
<p><span lang=EN-US>4</span><span style="FONT-FAMILY: 宋体">．结合</span><span lang=EN-US>save(),update(),saveOrUpdate()</span><span style="FONT-FAMILY: 宋体">方法说明对象的状态</span></p>
<p><span lang=EN-US><span></span>(1)Save()</span><span style="FONT-FAMILY: 宋体">方法将瞬时对象保存到数据库，对象的临时状态将变为持久化状态。当对象在持久化状态时，它一直位于</span><span lang=EN-US>Session</span><span style="FONT-FAMILY: 宋体">的缓存中，对它的任何操作在事务提交时都将同步到数据库，因此，对一个已经持久的对象调用</span><span lang=EN-US>save()</span><span style="FONT-FAMILY: 宋体">或</span><span lang=EN-US>update()</span><span style="FONT-FAMILY: 宋体">方法是没有意义的。如：</span></p>
<p><span lang=EN-US>Student stu = new Strudnet();</span></p>
<p><span lang=EN-US>stu.setCarId(&#8220;200234567&#8221;);</span></p>
<p><span lang=EN-US>stu.setId(&#8220;100&#8221;);</span></p>
<p><span lang=EN-US>//</span><span style="FONT-FAMILY: 宋体">打开</span><span lang=EN-US>Session,</span><span style="FONT-FAMILY: 宋体">开启事务</span></p>
<p><span lang=EN-US>session.save(stu);</span></p>
<p><span lang=EN-US>stu.setCardId(&#8220;20076548&#8221;);</span></p>
<p><span lang=EN-US>session.save(stu);<span> </span>//</span><span style="FONT-FAMILY: 宋体">无效</span></p>
<p><span lang=EN-US>session.update(stu); //</span><span style="FONT-FAMILY: 宋体">无效</span></p>
<p><span lang=EN-US>//</span><span style="FONT-FAMILY: 宋体">提交事务，关闭</span><span lang=EN-US>Session</span></p>
<p>
<p><span lang=EN-US><span></span>(2)update()</span><span style="FONT-FAMILY: 宋体">方法两种用途重新关联脱管对象为持久化状态对象，显示调用</span><span lang=EN-US>update()</span><span style="FONT-FAMILY: 宋体">以更新对象。调用</span><span lang=EN-US>update()</span><span style="FONT-FAMILY: 宋体">只为了关联一个脱管对象到持久状态，当对象已经是持久状态时，调用</span><span lang=EN-US>update()</span><span style="FONT-FAMILY: 宋体">就没有多大意义了。如：</span></p>
<p><span lang=EN-US>//</span><span style="FONT-FAMILY: 宋体">打开</span><span lang=EN-US>session</span><span style="FONT-FAMILY: 宋体">，开启事务</span></p>
<p><span lang=EN-US>stu = (Student)session.get(Student.class,&#8221;123456&#8221;);</span></p>
<p><span lang=EN-US>stu.setName(&#8220;Body&#8221;);</span></p>
<p><span lang=EN-US>session.update(stu);<span> </span><span></span>//</span><span style="FONT-FAMILY: 宋体">由于</span><span lang=EN-US>stu</span><span style="FONT-FAMILY: 宋体">是持久对象，必然位于</span><span lang=EN-US>Session</span><span style="FONT-FAMILY: 宋体">缓冲中，对</span><span lang=EN-US>stu</span><span style="FONT-FAMILY: 宋体">所做的变更将</span></p>
<p style="TEXT-INDENT: 68.25pt"><span lang=EN-US>//</span><span style="FONT-FAMILY: 宋体">被同步到数据库中。所以</span><span lang=EN-US>update()</span><span style="FONT-FAMILY: 宋体">是没有意义的，可以不要这句效果一样的。</span></p>
<p><span lang=EN-US>//</span><span style="FONT-FAMILY: 宋体">提交事务，关闭</span><span lang=EN-US>Session</span></p>
<p>
<p><span lang=EN-US><span></span>Hibernate</span><span style="FONT-FAMILY: 宋体">总是执行</span><span lang=EN-US>update</span><span style="FONT-FAMILY: 宋体">语句，不管这个脱管对象在离开</span><span lang=EN-US>Session</span><span style="FONT-FAMILY: 宋体">之后有没有更改过，在清理缓存时</span><span lang=EN-US>Hibernate</span><span style="FONT-FAMILY: 宋体">总是发送一条</span><span lang=EN-US>update</span><span style="FONT-FAMILY: 宋体">语句，以确保脱管对象和数据库记录的数据一致，如：</span></p>
<p><span lang=EN-US>Student stu = new Strudnet();</span></p>
<p><span lang=EN-US>stu.setCarId(&#8220;1234&#8221;);</span></p>
<p><span lang=EN-US>//</span><span style="FONT-FAMILY: 宋体">打开</span><span lang=EN-US>Session1,</span><span style="FONT-FAMILY: 宋体">开启事务</span></p>
<p><span lang=EN-US>session1.save(stu);</span></p>
<p><span lang=EN-US>//</span><span style="FONT-FAMILY: 宋体">提交事务，关闭</span><span lang=EN-US>Session1</span></p>
<p><span lang=EN-US>stu.set(&#8220;4567&#8221;);<span> </span>//</span><span style="FONT-FAMILY: 宋体">对脱管对象进行更改</span></p>
<p><span lang=EN-US>//</span><span style="FONT-FAMILY: 宋体">打开</span><span lang=EN-US>Session2,</span><span style="FONT-FAMILY: 宋体">开启事务</span></p>
<p><span lang=EN-US>session2.update(stu);</span></p>
<p><span lang=EN-US>//</span><span style="FONT-FAMILY: 宋体">提交事务，关闭</span><span lang=EN-US>Session2</span></p>
<p>
<p><span style="FONT-FAMILY: 宋体">注：即使把</span><span lang=EN-US>session2.update(stu);</span><span style="FONT-FAMILY: 宋体">这句去掉，提交事务时仍然会执行一条</span><span lang=EN-US>update()</span><span style="FONT-FAMILY: 宋体">语句。</span></p>
<p>
<p><span style="FONT-FAMILY: 宋体">如果希望只有脱管对象改变了，</span><span lang=EN-US>Hibernate</span><span style="FONT-FAMILY: 宋体">才生成</span><span lang=EN-US>update</span><span style="FONT-FAMILY: 宋体">语句，可以把映射文件中</span><span lang=EN-US>&lt;class&gt;</span><span style="FONT-FAMILY: 宋体">标签的</span><span lang=EN-US>select-before-update</span><span style="FONT-FAMILY: 宋体">设为</span><span lang=EN-US>true,</span><span style="FONT-FAMILY: 宋体">这种会先发送一条</span><span lang=EN-US>select</span><span style="FONT-FAMILY: 宋体">语句取得数据库中的值，判断值是否相同，如果相同就不执行</span><span lang=EN-US>update</span><span style="FONT-FAMILY: 宋体">语句。不过这种做法有一定的缺点，每次</span><span lang=EN-US>update</span><span style="FONT-FAMILY: 宋体">语句之前总是要发送一条多余的</span><span lang=EN-US>select</span><span style="FONT-FAMILY: 宋体">语句，影响性能。对于偶尔更改的类，设置才是有效的，对于经常要更改的类这样做是影响效率的。</span></p>
<p>
<p style="TEXT-INDENT: 15.75pt"><span lang=EN-US>(3)saveOrUpdate()</span><span style="FONT-FAMILY: 宋体">方法兼具</span><span lang=EN-US>save()</span><span style="FONT-FAMILY: 宋体">和</span><span lang=EN-US>update()</span><span style="FONT-FAMILY: 宋体">方法的功能，对于传入的对象，</span><span lang=EN-US>saveOrUpdate()</span><span style="FONT-FAMILY: 宋体">首先判断其是脱管对象还是临时对象，然后调用合适的方法。</span></p>
<img src ="http://www.blogjava.net/minghui/aggbug/134800.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/minghui/" target="_blank">星海拾贝</a> 2007-08-06 22:15 <a href="http://www.blogjava.net/minghui/articles/134800.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>