﻿<?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-henry1451 的专栏-文章分类-Hibernate技术</title><link>http://www.blogjava.net/henry1451/category/31255.html</link><description>共同学习,共同进步</description><language>zh-cn</language><lastBuildDate>Sun, 25 May 2008 12:39:57 GMT</lastBuildDate><pubDate>Sun, 25 May 2008 12:39:57 GMT</pubDate><ttl>60</ttl><item><title>Hibernate的cache管理(转)</title><link>http://www.blogjava.net/henry1451/articles/202718.html</link><dc:creator>henry1451</dc:creator><author>henry1451</author><pubDate>Sun, 25 May 2008 06:11:00 GMT</pubDate><guid>http://www.blogjava.net/henry1451/articles/202718.html</guid><wfw:comment>http://www.blogjava.net/henry1451/comments/202718.html</wfw:comment><comments>http://www.blogjava.net/henry1451/articles/202718.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/henry1451/comments/commentRss/202718.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/henry1451/services/trackbacks/202718.html</trackback:ping><description><![CDATA[<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #993366">Cache就是缓存，它往往是提高系统性能的最重要手段，对数据起到一个蓄水池和缓冲的作用。Cache对于大量依赖数据读取操作的系统而言尤其重要。在大并发量的情况下，如果每次程序都需要向数据库直接做查询操作，它们所带来的性能开销是显而易见的，频繁的网络舆，数据库磁盘的读写操作都会大大降低系统的性能。此时如果能让数据库在本地内存中保留一个镜像，下次访问的时候只需要从内存中直接获取，那么显然可以带来不小的性能提升。引入Cache机制的难点是如何保证内存中数据的有效性，否则脏数据的出现将会给系统带来难以预知的严重后果。虽然一个设计得很好的应用程序不用Cache也可以表现出让人接受的性能，但毫无疑问，一些对读取操作要求比较高的应用程序可以通过Cache获得更高的性能。对于应用程序，Cache通过内存或磁盘保存了数据库中的当前有关数据状态，它是一个存储在本地的数据备份。Cache位于数据库和应用程序之间，从数据库更新数据，并给程序提供数据。<br />
</span>Hibernate实现了良好的Cache机制，可以借助Hibernate内部的Cache迅速提高系统的数据读取性能。Hibernate中的Cache可分为两层：一级Cache和二级Cache。<br />
<span style="color: #0000ff"><strong style="background-color: #ccffff">一级Cache:<br />
</strong></span>Session实现了第一级Cache，它属于事务级数据缓冲。一旦事务结束，这个Cache也随之失效。一个Session的生命周期对应一个数据库事务或一个程序事务。<br />
Session-cache保证了一个Session中两次请求同一个对象时，取得的对象是同一个JAVA实例，有时它可以避免不必要的数据冲突。另外，它还能为另一些重要的性能提供保证：<br />
1：在对一个对象进行自我循环引用时， 不至于产生堆栈溢出。<br />
2：当数据库事务结束时，对于同一个数据库行，不会产生数据冲突，因为对于数据库中的一行，最多只有一个对象来表示它。<br />
3：一个事务中可能会有很多个处理单元，在每一个处理单元中做的操作都会立即被另外的处理单元得知。<br />
我们不用刻意去打开Session-cache，它总是被打开并且不能被关闭。当使用save(),update()或saveOrUpdate()来保存数据更改，或通过load(),find(),list()等方法来得到对象时，对象就会被加入到Session-cache。<br />
如果要同步很多数据对象，就需要有效地管理Cache,可以用Session的evict()方法从一级Cache中移除对象。如下：
<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.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">Session&nbsp;session&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;HibernateUtil.currentSession();<br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />Transaction&nbsp;tx&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;session.beginTransaction();<br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">for</span><span style="color: #000000">(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;i&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">&nbsp;;&nbsp;i&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">100000</span><span style="color: #000000">&nbsp;;&nbsp;i</span><span style="color: #000000">++</span><span style="color: #000000">)<br />
<img id="Codehighlighter1_128_185_Open_Image" onclick="this.style.display='none'; Codehighlighter1_128_185_Open_Text.style.display='none'; Codehighlighter1_128_185_Closed_Image.style.display='inline'; Codehighlighter1_128_185_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_128_185_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_128_185_Closed_Text.style.display='none'; Codehighlighter1_128_185_Open_Image.style.display='inline'; Codehighlighter1_128_185_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /></span><span id="Codehighlighter1_128_185_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.cnblogs.com/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_128_185_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;Student&nbsp;stu&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Student();<br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.cnblogs.com/Images/dot.gif"  alt="" /><br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;session.save(stu);<br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />}</span></span><span style="color: #000000"><br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />tx.commit();<br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />session.close();</span></div>
在保存50000个或更多对象时，程序可能会抛出OutOfMemoryException异常，因为Hibernate在一级Cache缓存了新加入的所有对象。内存溢出。要解决这全问题就需要把JDBC批处理数量设置为一个合理的数值（一般是10～20）。在Hibernate的配置文件中可以加入以下属性<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.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #0000ff">&lt;</span><span style="color: #800000">property&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">="hibernate.jdbc.batch_size"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">&nbsp;20&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">property</span><span style="color: #0000ff">&gt;</span></div>
<br />
然后我们在程序中一定时刻就提交并更新Session的Cache:
<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.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #000000">Session&nbsp;session&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;HibernateUtil.currentSession();<br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />Transaction&nbsp;tx&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;session.beginTransaction();<br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">for</span><span style="color: #000000">(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;i&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">&nbsp;;&nbsp;i&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">100000</span><span style="color: #000000">&nbsp;;&nbsp;i</span><span style="color: #000000">++</span><span style="color: #000000">)<br />
<img id="Codehighlighter1_128_287_Open_Image" onclick="this.style.display='none'; Codehighlighter1_128_287_Open_Text.style.display='none'; Codehighlighter1_128_287_Closed_Image.style.display='inline'; Codehighlighter1_128_287_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_128_287_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_128_287_Closed_Text.style.display='none'; Codehighlighter1_128_287_Open_Image.style.display='inline'; Codehighlighter1_128_287_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /></span><span id="Codehighlighter1_128_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.cnblogs.com/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_128_287_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;Student&nbsp;stu&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Student();<br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.cnblogs.com/Images/dot.gif"  alt="" /><br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;session.save(stu);<br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">(i</span><span style="color: #000000">%</span><span style="color: #000000">20</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">)&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">每保存完20个对象后，进行如下操作</span><span style="color: #008000"><br />
<img id="Codehighlighter1_221_285_Open_Image" onclick="this.style.display='none'; Codehighlighter1_221_285_Open_Text.style.display='none'; Codehighlighter1_221_285_Closed_Image.style.display='inline'; Codehighlighter1_221_285_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_221_285_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_221_285_Closed_Text.style.display='none'; Codehighlighter1_221_285_Open_Image.style.display='inline'; Codehighlighter1_221_285_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_221_285_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.cnblogs.com/Images/dot.gif"  alt="" /></span><span id="Codehighlighter1_221_285_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session.flush();</span><span style="color: #008000">//</span><span style="color: #008000">这个会提交更新</span><span style="color: #008000"><br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session.clear();</span><span style="color: #008000">//</span><span style="color: #008000">清除Cache,释放内存</span><span style="color: #008000"><br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"  alt="" />}</span></span><span style="color: #000000"><br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />tx.commit();<br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />session.close();</span></div>
<p><span style="color: #0000ff"><strong style="background-color: #ccffff">二级Cache<br />
</strong></span>二级Cache是SessionFactory范围内的缓存，所有的Session共享同一个二级Cache。在二级Cache中保存持久性实例的散装形式的数据。二级Cache的内部如何实现并不重要，重要的是采用哪种正确的缓存策略，以及采用哪个Cache提供器。持久化不同的数据需要不同的Cache策略，比如一些因素将影响到Cache策略的选择：数据的读/写比例，数据表是否能被其他的应用程序扬访问等。对于一些读/写比例高的数据可以打开它的缓存，允许这些数据进入二级缓存容器有利于系统性能的优化;而对于能被其它应用程序访问的数据对象，最好将此对象的二级Cache选项关闭。<br />
设置Hibernate的二级Cache需要分两步进行：首先确认使用什么数据并发策略，然后配置缓存过期时间并设置Cache提供器。<br />
有4种内置的Hibernate数据并发冲突策略，代表数据库隔离级别，如下：<br />
1：<span style="color: #0000ff">事务（Transaction）</span>仅在受管理的环境中可用。它保证可重读的事务隔离级别，可以对读/写比例高，很少更新的数据采用该策略。<br />
2：<span style="color: #0000ff">读写（read-write）</span>使用时间戳机制维护读写提交事务隔离级别。可以对读/写比例高，很少更新的数据采用该策略。<br />
3：<span style="color: #0000ff">非严格读写（notstrict-read-write）</span>不保证Cache和数据库之间的数据库的一致性。使用此策略时，应该设置足够的缓存过期时间，否则可能从缓存中读出脏数据。当一些数据极少改变，并且当这些数据和数据库有一部份不量影响不大时，可以使用此策略。<br />
4：<span style="color: #0000ff">只读（read-only）</span>当确保数据永不改变时，可以使用此策略。</p>
<p>我们确定了Cache策略后，就要挑选一个高效的Cache提供器，它将作为插件被Hibernate调用。Hibernate允许使用下述几种缓存插件：<br />
EhCache：可以在JVM中作为一个简单进程范围内的缓存，它可以把缓存的数据放入内存或磁盘，并支持Hibernate中可选用的查询缓存。<br />
OpenSymphony OSCache：和EhCache相似，并且提供了丰富的缓存过期策略。<br />
SwarmCache：可作为集群范围的缓存，但不支持查询缓存。<br />
JBossCache：可作为集群范围的缓冲，但不支持查询缓存。</p>
<p><span style="color: #0000ff; background-color: #ccffff">在Hibernate中使用EhCache</span><br />
EhCache是一个纯JAVA程序，可以在Hibernate中作为一个插件引入。在Hibernate中使用EhCache需要在Hibernate的配置文件中设置如下：</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 src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #0000ff">&lt;</span><span style="color: #800000">propery&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">="hibernate.cache.provider_class"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;org.hibernate.cache.EhCacheProvider<br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">property</span><span style="color: #0000ff">&gt;</span></div>
EhCacheProvider类是位于Hibernate3.jar包中而不是ehcache-1.1.jar包中。EhCache有自己的配置文档，名为chcache.xml。Hibernate3.x中的etc目录下有ehcache.xml的示例文件，只须要将 它COPY到我们的应用程序src目录下（编译时会把ehcache.xmlCOPY到WEB-INF/classes目录下）。对其中的相关值进行更改以和自己的程序相适应。进行配置后，在ehcache.xml文件中的代码如下：
<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.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #0000ff">&lt;</span><span style="color: #800000">ehcache</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">diskStore&nbsp;</span><span style="color: #ff0000">path</span><span style="color: #0000ff">="c:\\cache"</span><span style="color: #0000ff">/&gt;</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;//设置cache.data文件存放位置<br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">defaultCache<br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #ff0000">maxElementsInMemory</span><span style="color: #0000ff">="10000"</span><span style="color: #ff0000">&nbsp;//缓存中允许创建的最大对象数<br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eternal</span><span style="color: #0000ff">="false"</span><span style="color: #ff0000">&nbsp;&nbsp;&nbsp;&nbsp;//缓存中对象是否为永久的<br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeToIdleSeconds</span><span style="color: #0000ff">="120"</span><span style="color: #ff0000">//缓存数据钝化时间(即对象在它过期前的空闲时间)<br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeToLiveSeconds</span><span style="color: #0000ff">="120"</span><span style="color: #ff0000">//缓存数据生存时间(即对象在它过期前的生存时间)<br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;overflowToDisk</span><span style="color: #0000ff">="true"</span><span style="color: #ff0000"><br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">/&gt;</span><span style="color: #000000"><br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;<br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">cache&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">="Student"</span><span style="color: #ff0000">&nbsp;&nbsp;&nbsp;&nbsp;//用户自定义的Cache配置<br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;maxElementsInMemory</span><span style="color: #0000ff">="10000"</span><span style="color: #ff0000"><br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;eternal</span><span style="color: #0000ff">="false"</span><span style="color: #ff0000"><br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeToIdleSeconds</span><span style="color: #0000ff">="300"</span><span style="color: #ff0000"><br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;timeToLiveSeconds</span><span style="color: #0000ff">="600"</span><span style="color: #ff0000"><br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;overflowToDisk</span><span style="color: #0000ff">="true"</span><span style="color: #ff0000"><br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">/&gt;</span><span style="color: #000000"><br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">ehcache</span><span style="color: #0000ff">&gt;</span></div>
此外我们还需要在持久化类的映射文件中进行配置。例如，Group(班级)和Student(学生)是一对多的关系，它们对应的数据表分别是t_group和t_student。现在要把Student类的数据进行二级缓存，这需要在二个映射文件中都对二级缓存进行配置。<br />
在Group.hbm.xml中如下<br />
在其&lt;set&gt;&lt;/set&gt;中添加
<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.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #0000ff">&lt;</span><span style="color: #800000">cache&nbsp;</span><span style="color: #ff0000">usage</span><span style="color: #0000ff">="read-write"</span><span style="color: #0000ff">/&gt;</span><span style="color: #008000">&lt;!--</span><span style="color: #008000">集合中的数据被缓存</span><span style="color: #008000">--&gt;</span></div>
上述文件虽然在&lt;set&gt;标记中设置了&lt;cache usage="read-write"/&gt;，<span style="color: #0000ff">但Hibernate只是把Group相关的Student的主键ID加入到缓存中，如果希望把整个Student的散装属性都加入到二级缓存中，还需要在Student.hbm.xml文件的&lt;class&gt;标记中添加&lt;cache&gt;子标记</span>。如下：
<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.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #0000ff">&lt;</span><span style="color: #800000">class&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">="Student"</span><span style="color: #ff0000">&nbsp;table</span><span style="color: #0000ff">="t_student"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">cache&nbsp;</span><span style="color: #ff0000">usage</span><span style="color: #0000ff">="read-write"</span><span style="color: #ff0000">&nbsp;</span><span style="color: #0000ff">/&gt;</span><span style="color: #008000">&lt;!--</span><span style="color: #008000">cache标记需跟在class标记后</span><span style="color: #008000">--&gt;</span><span style="color: #000000"><br />
<img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">class</span><span style="color: #0000ff">&gt;</span></div>
<img src ="http://www.blogjava.net/henry1451/aggbug/202718.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/henry1451/" target="_blank">henry1451</a> 2008-05-25 14:11 <a href="http://www.blogjava.net/henry1451/articles/202718.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate多表关联 </title><link>http://www.blogjava.net/henry1451/articles/201294.html</link><dc:creator>henry1451</dc:creator><author>henry1451</author><pubDate>Sun, 18 May 2008 12:47:00 GMT</pubDate><guid>http://www.blogjava.net/henry1451/articles/201294.html</guid><wfw:comment>http://www.blogjava.net/henry1451/comments/201294.html</wfw:comment><comments>http://www.blogjava.net/henry1451/articles/201294.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/henry1451/comments/commentRss/201294.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/henry1451/services/trackbacks/201294.html</trackback:ping><description><![CDATA[<br />
<span style="color: #993300">一、多对一进行关联(多个学生对应同一间宿舍)---学生是主体，宿舍是附体，关联关系&lt;many-to-one&gt;在主体学生中设置，在学生类中设置宿舍类，由于宿舍类只有一个可以直接用类来设置,在映射学生类(User)中包含宿舍这个类(Room),在映射配置文件(User.hbm.xml)中定义<br />
<br />
<span style="color: #008080">&lt;many-to-one name="room" column="room_id" cascade="save-update" class="com.wyq.hibernate2.Room"&gt;&lt;/many-to-one&gt;<br />
<br />
</span>哪个是主体类就在哪个配置文件定义关联关系．<br />
<br />
<span style="color: #800080">cascade属性：表示关联对象的持久化，该属性也要设置在主体中，作用就是当主控方执行操作时，关联对象(被动方)是否同步执行同一操作．<br />
cascade的值：all:表示所有情况下都进行级联操作．<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;none:所有情况下都不进行级联操作<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;save-update:在执行save-update时进行级联操作．<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;delete:在执行delete时进行级联操作．</span><br />
注意：使用cascade自動持久化時，會先檢查被關聯物件的id屬性，未被持久化的物件之id屬性是由unsaved-value決定，預設是null，如果您使用long這樣的原生型態（primitive type）時，則必須自行指定預設值．<br />
<br />
<span style="color: #008080">例如：&lt;id name="id" column="ROOM_ID" unsaved-value="0"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;generator class="increment"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/id&gt;<br />
</span><br />
如果您不想額外設定unsaved-value資訊，則可以將long改為Long，這可以符合預設的unsaved-value為null的設定&nbsp;．<br />
<br />
二、一对多进行关联(一间宿舍对应多个学生)---宿舍是主体，学生是附体，关联关系&lt;one-to-many&gt;在主体宿舍中设置,由于要在宿舍类中设置学生类，一个宿舍包含多个学生，所以在宿舍类中要用Set类来进行设置，用set类(private Set users = new HashSet();)来存储多个学生类，在映射宿舍类(Room)中要包含&lt;set&gt;这个节点，用来与user相关联<br />
<br />
<span style="color: #008080">例如：&lt;set name="users" table="USER"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;key column="ROOM_ID"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;one-to-many class="onlyfun.caterpillar.User"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/set&gt;<br />
</span><br />
<span style="color: #800080">name:表示属性，table:表示关联的表名，key:表示通过什么字段进行关联，&lt;one-to-many&gt;:表示关联类。这里也可以使用cascade属性。<br />
</span><br />
三、在表关联的设计中，不论是一对多还是多对一，都要将关联字段设置在多的那一方。<br />
例如：user表格和room表格，要将关联字段room_id设置在user表格中。<br />
<br />
四、一对一进行关联(一个人只有一个房间，一个房间也只有一个人)。<br />
可以通过２中方式进行关联：<br />
<br />
(1)、通过外键进行关联：在多对一的例子中就是通过外键进行关联的.<br />
在user-room的设置中(user.hbm.xml):<br />
<span style="color: #008080">&lt;many-to-one name="room"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; column="ROOM_ID"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="onlyfun.caterpillar.Room" <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cascade="all"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unique="true"/&gt;</span> <br />
其中unique表示限制一個User有一獨有的 Room，这只是单向的，说明一个user只有一个room.<br />
在room-user的设置中(room.hbm.xml):<br />
&lt;one-to-one name="user"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="onlyfun.caterpillar.User"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; property-ref="room"/&gt;<br />
这样就完成了双向的一对一关联，property-ref告诉hibernate,查询出user并将其参考至room。<br />
(2)、通过主键进行关联：限制兩個資料表的主鍵使用相同的值，如此一個User與Room就是一對一關係<br />
<span style="color: #008080">user.hbm.xml:<br />
&lt;one-to-one name="room"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="onlyfun.caterpillar.Room"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cascade="all"/&gt; <br />
room.hbm.xml:<br />
&lt;one-to-one name="user"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="onlyfun.caterpillar.User"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; constrained="true"/&gt;</span><br />
使用constrained="true"告訴Hibernate參考至User的主鍵<br />
<br />
五、双向关联，就是将一和二结合起来，<font color="#000000"><span style="color: #993300">如果將關聯的維護交給User的話會比較容易，因為每個User都對應至一個Room，在儲存時並用像Room一樣必須對Set中的每個物件作檢查，為了將關聯的維護交給User，我們可以在Room.hbm.xml中的&lt;set&gt;修改，加上inverse="true"，表示將關聯的維護「反過來」交給User作</span></font><font style="color: #993300"><br />
<br />
&nbsp;<span style="color: #008080">例如：&lt;set name="users" table="users" iinverse="true" cascade="all"&gt;<br />
</span></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #008080">&lt;key&nbsp; column="room_id"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;one-to-many class="onlyfun.caterpillar.User"/&gt;<br />
<br />
<font color="#993300">在設立雙向關聯時，關聯由多對一中「多」的哪一方維護，會比由「一」的哪一方維護來的方便，在Hibernate可以藉由inverse來設定，不設定inverse基本上也可以運行，但是效能會較差</font></span></span>&nbsp;
<img src ="http://www.blogjava.net/henry1451/aggbug/201294.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/henry1451/" target="_blank">henry1451</a> 2008-05-18 20:47 <a href="http://www.blogjava.net/henry1451/articles/201294.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate使用criteria进行查询</title><link>http://www.blogjava.net/henry1451/articles/201293.html</link><dc:creator>henry1451</dc:creator><author>henry1451</author><pubDate>Sun, 18 May 2008 12:41:00 GMT</pubDate><guid>http://www.blogjava.net/henry1451/articles/201293.html</guid><wfw:comment>http://www.blogjava.net/henry1451/comments/201293.html</wfw:comment><comments>http://www.blogjava.net/henry1451/articles/201293.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/henry1451/comments/commentRss/201293.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/henry1451/services/trackbacks/201293.html</trackback:ping><description><![CDATA[<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #800080">1、读取配置文件获得连接<br />
</span>&nbsp;&nbsp;&nbsp;<span style="color: #993300">读取hibernate.cfg.xml配置文件，hibernate.cfg.xml文件放在Classpath下，使用下面的方式读入该文件</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #339966">//Configuration 负责管理hibernate配置信息</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Configuration config=new Configuration().configure();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #339966">//根据config建立SessionFactory<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//SessionFactory用于建立Session<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SessionFactory sessionFactory=config.buildSessionFactory();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #339966">//开启session,相当于jdbc的Connection<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session = sessionFactory.openSession();<br />
<br />
<span style="color: #800080">2、Criteria 基本资料查询<br />
(1)标准查询:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #339966">//创建查询标准<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Criteria criteria=session.creteCriteria(User.class);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #339966">//查询条件<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;criteria.add(Expression.eq("name","caterpillar"));<br />
<span style="color: #339966">************************************************************************************<br />
</span><span style="color: #3366ff">Expression.eq(String s1,String s2)----------&gt;相等s1=s2<br />
Expression.allEq(Map map)&nbsp;&nbsp;&nbsp; ---------------&gt;多个属性-值对应关系，多个Expression.eq叠加<br />
Expression.gt(String s1,String s2)-----------&gt;大于s1&gt;s2<br />
Expression.ge(String s1,String s2)-----------&gt;大于等于s1&gt;=s2<br />
Expression.lt(String s1,String s2)------------&gt;小于s1&lt;s2<br />
Expression.le(String s1,String s2)------------&gt;小于等于s1&lt;=s2<br />
Expression.between(String s1,int s2,int s3)---&gt;s2&lt;s1&lt;s3<br />
Expression.like(String s1,String s2)------------&gt;s1 like s2<br />
比较2个属性<br />
Expression.eqProperty(String s1,String s2)---&gt;s1=s2<br />
Expression.gtProperty(String s1,String s2)----&gt;s1&gt;s2<br />
Expression.geProperty(String s1,String s2)----&gt;s1&gt;=s2<br />
Expression.ltProperty(String s1,String s2)-----&gt;s1&lt;s2<br />
Expression.leProperty(String s1,String s2)-----&gt;s1&lt;=s2<br />
Expression.and()-----&gt;Expression.and(Expression.eq("String s1,String s2"),Expression.eq(String s3,String s4))<br />
Expression.or()<br />
</span><span style="color: #339966">************************************************************************************<br />
</span>(2)高级查询<br />
一、可以使用Criteria进行查询，并用order对结果进行排序。<br />
<span style="color: #3366ff">//设置从第几条开始取的记录<br />
criteria.setFirstResult(100);<br />
//最多取的几条记录<br />
criteria.setMaxResults(20);<br />
//对结果进行排序<br />
criteria.addOrder(Order.asc(String s1));<br />
criteria.addOrder(Order.desc(String s2));<br />
<br />
<span style="color: #800080">二、可以对查询结果进行统计操作，使用Projections的rowCount(),count(),max(),min</span>(),countDistinct()等方法：<br />
例如：criteria.setProjection(Projections.max("age"));<br />
<br />
<span style="color: #800080">三、还可以用Projections的groupProperty()来对结果进行分组</span><br />
例如：criteria.setProjection(Projections.groupProperty("age"));<br />
<br />
<span style="color: #800080">(***)四、结合统计与分组的功能，可以用ProjectionList</span><br />
例如：ProjectionList projectionList =Projections.projectionList();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;projectionList.add(Projections.groupProperty("age"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;projectionList.add(Projections.rowCount());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;criteria.setProjection(projectionList);<br />
</span><span style="color: #339966">^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #339966">//查询所有记录<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List users=criteria.list();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterator iterator=users.iterator();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(iterator.hasNext()){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;User user=(User)iterator.next();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(user.getId()+"\t"+user.getName()+"/"+user.getAge());<br />
}<br />
3、criteria的增、删、改（还不完善）<br />
在用到增、删、改时，必须先声明事务<br />
增加：<br />
&nbsp;&nbsp;<span style="color: #3366ff">Transaction tx = session.beginTransaction();//Transaction表示一组会话操作<br />
&nbsp;&nbsp;session.save(user);//将事物映射到数据库进行存储<br />
&nbsp;&nbsp;tx.commit();<br />
&nbsp;&nbsp;session.close();<br />
</span>删除：<br />
&nbsp;&nbsp;<span style="color: #3366ff">Session session=this.getSession();<br />
&nbsp;&nbsp;User user=(User)session.get(User.class, new Integer(1));<br />
&nbsp;&nbsp;Transaction tx = session.beginTransaction();//Transaction表示一组会话操作<br />
&nbsp;&nbsp;session.delete(user);//将事物映射到数据库进行存储<br />
&nbsp;&nbsp;tx.commit();<br />
&nbsp;&nbsp;session.close();</span><br />
修改：<br />
&nbsp;&nbsp;<span style="color: #3366ff">Session session=this.getSession();<br />
&nbsp;&nbsp;User user =(User)session.get(User.class,new Integer(2));//创建持久化的事物<br />
&nbsp;&nbsp;user.setName("wyqqqqqqqqqq");<br />
&nbsp;&nbsp;user.setAge(new Integer(30));<br />
&nbsp;&nbsp;Transaction tx = session.beginTransaction();//Transaction表示一组会话操作<br />
</span>&nbsp;&nbsp;<span style="color: #3366ff">session.update(user);//将事物映射到数据库进行存储<br />
&nbsp;&nbsp;tx.commit();<br />
&nbsp;&nbsp;session.close();<br />
</span></span>
<img src ="http://www.blogjava.net/henry1451/aggbug/201293.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/henry1451/" target="_blank">henry1451</a> 2008-05-18 20:41 <a href="http://www.blogjava.net/henry1451/articles/201293.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate中session的管理</title><link>http://www.blogjava.net/henry1451/articles/201292.html</link><dc:creator>henry1451</dc:creator><author>henry1451</author><pubDate>Sun, 18 May 2008 12:36:00 GMT</pubDate><guid>http://www.blogjava.net/henry1451/articles/201292.html</guid><wfw:comment>http://www.blogjava.net/henry1451/comments/201292.html</wfw:comment><comments>http://www.blogjava.net/henry1451/articles/201292.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/henry1451/comments/commentRss/201292.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/henry1451/services/trackbacks/201292.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session是hibernate运做的核心，是有SessionFactory所创建，sessionFactory是线程安全的，你可以让多个线程同时存取SessionFactory,而不会有资源共用的问题，然而session不是设计为线程安全的，所以让多个线程共用一个session，将发生资料共用而发生...&nbsp;&nbsp;<a href='http://www.blogjava.net/henry1451/articles/201292.html'>阅读全文</a><img src ="http://www.blogjava.net/henry1451/aggbug/201292.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/henry1451/" target="_blank">henry1451</a> 2008-05-18 20:36 <a href="http://www.blogjava.net/henry1451/articles/201292.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在Hibernate应用中如何处理批量更新和批量删除(转)</title><link>http://www.blogjava.net/henry1451/articles/196481.html</link><dc:creator>henry1451</dc:creator><author>henry1451</author><pubDate>Sun, 27 Apr 2008 08:33:00 GMT</pubDate><guid>http://www.blogjava.net/henry1451/articles/196481.html</guid><wfw:comment>http://www.blogjava.net/henry1451/comments/196481.html</wfw:comment><comments>http://www.blogjava.net/henry1451/articles/196481.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/henry1451/comments/commentRss/196481.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/henry1451/services/trackbacks/196481.html</trackback:ping><description><![CDATA[<div class="postText">批量更新是指在一个事务中更新大批量数据，批量删除是指在一个事务中删除大批量数据。以下程序直接通过Hibernate API批量更新CUSTOMERS表中年龄大于零的所有记录的AGE字段：<br />
<br />
tx = session.beginTransaction();<br />
Iterator customers=session.find("from Customer c where c.age&gt;0").iterator();<br />
while(customers.hasNext()){<br />
Customer customer=(Customer)customers.next();<br />
customer.setAge(customer.getAge()+1);<br />
} <br />
tx.commit();<br />
session.close();<br />
<br />
如果CUSTOMERS表中有1万条年龄大于零的记录，那么Session的find()方法会一下子加载1万个Customer对象到内存。当执行tx.commit()方法时，会清理缓存，Hibernate执行1万条更新CUSTOMERS表的update语句：<br />
<br />
update CUSTOMERS set AGE=? &#8230;. where ID=i;<br />
update CUSTOMERS set AGE=? &#8230;. where ID=j;<br />
update CUSTOMERS set AGE=? &#8230;. where ID=k;<br />
<br />
以上批量更新方式有两个缺点：<br />
(1) 占用大量内存，必须把1万个Customer对象先加载到内存，然后一一更新它们。<br />
(2) 执行的update语句的数目太多，每个update语句只能更新一个Customer对象，必须通过1万条update语句才能更新一万个Customer对象，频繁的访问数据库，会大大降低应用的性能。<br />
为了迅速释放1万个Customer对象占用的内存，可以在更新每个Customer对象后，就调用Session的evict()方法立即释放它的内存：<br />
<br />
tx = session.beginTransaction();<br />
Iterator customers=session.find("from Customer c where c.age&gt;0").iterator();<br />
while(customers.hasNext()){<br />
Customer customer=(Customer)customers.next();<br />
customer.setAge(customer.getAge()+1);<br />
session.flush();<br />
session.evict(customer);<br />
} <br />
tx.commit();<br />
session.close();<br />
<br />
在以上程序中，修改了一个Customer对象的age属性后，就立即调用Session的flush()方法和evict()方法，flush()方法使Hibernate立刻根据这个Customer对象的状态变化同步更新数据库，从而立即执行相关的update语句；evict()方法用于把这个Customer对象从缓存中清除出去，从而及时释放它占用的内存。<br />
但evict()方法只能稍微提高批量操作的性能，因为不管有没有使用evict()方法，Hibernate都必须执行1万条update语句，才能更新1万个Customer对象，这是影响批量操作性能的重要因素。假如Hibernate能直接执行如下SQL语句：<br />
<br />
update CUSTOMERS set AGE=AGE+1 where AGE&gt;0;<br />
<br />
那么以上一条update语句就能更新CUSTOMERS表中的1万条记录。但是Hibernate并没有直接提供执行这种update语句的接口。应用程序必须绕过Hibernate API，直接通过JDBC API来执行该SQL语句：<br />
<br />
tx = session.beginTransaction();<br />
Connection con=session.connection();<br />
PreparedStatement stmt=con.prepareStatement("update CUSTOMERS set AGE=AGE+1 "<br />
+"where AGE&gt;0 ");<br />
stmt.executeUpdate();<br />
tx.commit();<br />
<br />
以上程序演示了绕过Hibernate API，直接通过JDBC API访问数据库的过程。应用程序通过Session的connection()方法获得该Session使用的数据库连接，然后通过它创建PreparedStatement对象并执行SQL语句。值得注意的是，应用程序仍然通过Hibernate的Transaction接口来声明事务边界。<br />
如果底层数据库（如Oracle）支持存储过程，也可以通过存储过程来执行批量更新。存储过程直接在数据库中运行，速度更加快。在Oracle数据库中可以定义一个名为batchUpdateCustomer()的存储过程，代码如下：<br />
<br />
create or replace procedure batchUpdateCustomer(p_age in number) as<br />
begin<br />
update CUSTOMERS set AGE=AGE+1 where AGE&gt;p_age;<br />
end;<br />
<br />
以上存储过程有一个参数p_age，代表客户的年龄，应用程序可按照以下方式调用存储过程：<br />
tx = session.beginTransaction();<br />
Connection con=session.connection();<br />
String procedure = "{call batchUpdateCustomer(?) }";<br />
CallableStatement cstmt = con.prepareCall(procedure);<br />
cstmt.setInt(1,0); //把年龄参数设为0<br />
cstmt.executeUpdate();<br />
tx.commit();<br />
<br />
从上面程序看出，应用程序也必须绕过Hibernate API，直接通过JDBC API来调用存储过程。<br />
Session的各种重载形式的update()方法都一次只能更新一个对象，而delete()方法的有些重载形式允许以HQL语句作为参数，例如：<br />
<br />
session.delete("from Customer c where c.age&gt;0");<br />
<br />
如果CUSTOMERS表中有1万条年龄大于零的记录，那么以上代码能删除一万条记录。但是Session的delete()方法并没有执行以下delete语句<br />
<br />
delete from CUSTOMERS where AGE&gt;0;<br />
<br />
Session的delete()方法先通过以下select语句把1万个Customer对象加载到内存中：<br />
<br />
select * from CUSTOMERS where AGE&gt;0;<br />
<br />
接下来执行一万条delete语句，逐个删除Customer对象：<br />
<br />
delete from CUSTOMERS where ID=i;<br />
delete from CUSTOMERS where ID=j;<br />
delete from CUSTOMERS where ID=k;<br />
<br />
由此可见，直接通过Hibernate API进行批量更新和批量删除都不值得推荐。而直接通过JDBC API执行相关的SQL语句或调用相关的存储过程，是批量更新和批量删除的最佳方式，这两种方式都有以下优点：<br />
<br />
(1) 无需把数据库中的大批量数据先加载到内存中，然后逐个更新或修改它们，因此不会消耗大量内存。<br />
(2) 能在一条SQL语句中更新或删除大批量的数据。 </div>
 <img src ="http://www.blogjava.net/henry1451/aggbug/196481.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/henry1451/" target="_blank">henry1451</a> 2008-04-27 16:33 <a href="http://www.blogjava.net/henry1451/articles/196481.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>