﻿<?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-贫以智为贵,富以仁为贵.-文章分类-Hibernate专题</title><link>http://www.blogjava.net/LeungXin/category/26011.html</link><description /><language>zh-cn</language><lastBuildDate>Sun, 16 Dec 2007 13:47:29 GMT</lastBuildDate><pubDate>Sun, 16 Dec 2007 13:47:29 GMT</pubDate><ttl>60</ttl><item><title>spring中配置hibernate二级缓存 </title><link>http://www.blogjava.net/LeungXin/articles/167384.html</link><dc:creator>梁昕</dc:creator><author>梁昕</author><pubDate>Thu, 13 Dec 2007 01:32:00 GMT</pubDate><guid>http://www.blogjava.net/LeungXin/articles/167384.html</guid><description><![CDATA[<p>1.首先,在spring的hibernate配置里(我的是applicationContext-hibernate.xml)&nbsp;加上如下属性:</p>
<p>&lt;bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"&gt;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&lt;property name="dataSource"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;ref bean="dataSource"/&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="mappingResources"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;list&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;org/appfteaching/model/TArticleclass.hbm.xml&lt;/value&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;/list&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&lt;property name="hibernateProperties"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;props&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;prop key="hibernate.dialect"&gt;${hibernate.dialect}&lt;/prop&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="hibernate.show_sql"&gt;${hibernate.show_sql}&lt;/prop&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="hibernate.jdbc.fetch_size"&gt;${hibernate.jdbc.fetch_size}&lt;/prop&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="hibernate.jdbc.batch_size"&gt;${hibernate.jdbc.batch_size}&lt;/prop&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="#ff0000">&lt;prop key="hibernate.cache.use_query_cache"&gt;true&lt;/prop&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="hibernate.cache.provider_class"&gt;org.hibernate.cache.EhCacheProvider&lt;/prop&gt;<br />
</font>&nbsp;&nbsp;&nbsp;&lt;/props&gt;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&lt;/property&gt;&nbsp;&nbsp;<br />
&nbsp;&lt;/bean&gt;&nbsp;</p>
<p>2.其次,在src目录下的ehcache.xml中配置如下信息(如果是默认ehcache.xml则会有&lt;cache name="sampleCache1"&gt;和&lt;cache name="sampleCache2&gt;",去掉)</p>
<p>&lt;cache name="org.hibernate.cache.StandardQueryCache"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxElementsInMemory="10000"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eternal="false"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToIdleSeconds="300"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToLiveSeconds="4200"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; overflowToDisk="true"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /&gt;</p>
<p>&nbsp;&nbsp;&nbsp; &lt;!-- Sample cache named sampleCache2<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; This cache contains 1000 elements. Elements will always be held in memory.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; They are not expired. --&gt;</p>
<p>&nbsp;&nbsp;&nbsp; &lt;cache name="org.hibernate.cache.UpdateTimestampsCache"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxElementsInMemory="5000"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eternal="true"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToIdleSeconds="0"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToLiveSeconds="0"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; overflowToDisk="false"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /&gt; </p>
<p>3.将你要缓存的model加进ehcache.xml里</p>
<p>&lt;cache name="org.appfteaching.model.TArticleclass" <br />
&nbsp;&nbsp;&nbsp; &nbsp;maxElementsInMemory="1000"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eternal="false"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToIdleSeconds="100"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToLiveSeconds="4200"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; overflowToDisk="true"<br />
&nbsp;&nbsp;&nbsp; &nbsp;/&gt;&nbsp;&nbsp; </p>
<p>4.最后一步,在TArticleclass.hbm.xml里加上</p>
<p>&lt;cache usage="read-write"/&gt;</p>
<p>启动Tomcat,如发现如下错误</p>
<p>Could not find configuration [org.hibernate.cache.UpdateTimestampsCache]; using defaults.<br />
Could not find configuration [org.hibernate.cache.StandardQueryCache]; using defaults.</p>
<p>则是第二步没有做,加上即可.配置完毕</p>
spring中配置二级缓存&nbsp;
<img src ="http://www.blogjava.net/LeungXin/aggbug/167384.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/LeungXin/" target="_blank">梁昕</a> 2007-12-13 09:32 <a href="http://www.blogjava.net/LeungXin/articles/167384.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hibernate二级缓存攻略(转)</title><link>http://www.blogjava.net/LeungXin/articles/167290.html</link><dc:creator>梁昕</dc:creator><author>梁昕</author><pubDate>Wed, 12 Dec 2007 10:02:00 GMT</pubDate><guid>http://www.blogjava.net/LeungXin/articles/167290.html</guid><description><![CDATA[<p>很多人对二级缓存都不太了解，或者是有错误的认识，我一直想写一篇文章介绍一下hibernate的二级缓存的，今天终于忍不住了。 <br />
我的经验主要来自hibernate2.1版本，基本原理和3.0、3.1是一样的，请原谅我的顽固不化。</p>
<p>hibernate的session提供了一级缓存，每个session，对同一个id进行两次load，不会发送两条sql给数据库，但是session关闭的时候，一级缓存就失效了。</p>
<p>二级缓存是SessionFactory级别的全局缓存，它底下可以使用不同的缓存类库，比如ehcache、oscache等，需要设置hibernate.cache.provider_class，我们这里用ehcache，在2.1中就是 <br />
hibernate.cache.provider_class=net.sf.hibernate.cache.EhCacheProvider <br />
如果使用查询缓存，加上 <br />
hibernate.cache.use_query_cache=true</p>
<p>缓存可以简单的看成一个Map，通过key在缓存里面找value。</p>
<p><strong>Class的缓存</strong> <br />
对于一条记录，也就是一个PO来说，是根据ID来找的，缓存的key就是ID，value是POJO。无论list，load还是iterate，只要读出一个对象，都会填充缓存。但是list不会使用缓存，而iterate会先取数据库select id出来，然后一个id一个id的load，如果在缓存里面有，就从缓存取，没有的话就去数据库load。假设是读写缓存，需要设置： <br />
&lt;cache usage="read-write"/&gt; <br />
如果你使用的二级缓存实现是ehcache的话，需要配置ehcache.xml <br />
&lt;cache name="com.xxx.pojo.Foo" maxElementsInMemory="500" eternal="false" timeToLiveSeconds="7200" timeToIdleSeconds="3600" overflowToDisk="true" /&gt; <br />
其中eternal表示缓存是不是永远不超时，timeToLiveSeconds是缓存中每个元素（这里也就是一个POJO）的超时时间，如果eternal="false"，超过指定的时间，这个元素就被移走了。timeToIdleSeconds是发呆时间，是可选的。当往缓存里面put的元素超过500个时，如果overflowToDisk="true"，就会把缓存中的部分数据保存在硬盘上的临时文件里面。 <br />
每个需要缓存的class都要这样配置。如果你没有配置，hibernate会在启动的时候警告你，然后使用defaultCache的配置，这样多个class会共享一个配置。 <br />
当某个ID通过hibernate修改时，hibernate会知道，于是移除缓存。 <br />
这样大家可能会想，同样的查询条件，第一次先list，第二次再iterate，就可以使用到缓存了。实际上这是很难的，因为你无法判断什么时候是第一次，而且每次查询的条件通常是不一样的，假如数据库里面有100条记录，id从1到100，第一次list的时候出了前50个id，第二次iterate的时候却查询到30至70号id，那么30-50是从缓存里面取的，51到70是从数据库取的，共发送1+20条sql。所以我一直认为iterate没有什么用，总是会有1+N的问题。 <br />
（题外话：有说法说大型查询用list会把整个结果集装入内存，很慢，而iterate只select id比较好，但是大型查询总是要分页查的，谁也不会真的把整个结果集装进来，假如一页20条的话，iterate共需要执行21条语句，list虽然选择若干字段，比iterate第一条select id语句慢一些，但只有一条语句，不装入整个结果集hibernate还会根据数据库方言做优化，比如使用mysql的limit，整体看来应该还是list快。） <br />
如果想要对list或者iterate查询的结果缓存，就要用到查询缓存了</p>
<p><strong>查询缓存</strong> <br />
首先需要配置hibernate.cache.use_query_cache=true <br />
如果用ehcache，配置ehcache.xml，注意hibernate3.0以后不是net.sf的包名了 <br />
&lt;cache name="net.sf.hibernate.cache.StandardQueryCache" <br />
maxElementsInMemory="50" eternal="false" timeToIdleSeconds="3600" <br />
timeToLiveSeconds="7200" overflowToDisk="true"/&gt; <br />
&lt;cache name="net.sf.hibernate.cache.UpdateTimestampsCache" <br />
maxElementsInMemory="5000" eternal="true" overflowToDisk="true"/&gt; <br />
然后 <br />
query.setCacheable(true);//激活查询缓存 <br />
query.setCacheRegion("myCacheRegion");//指定要使用的cacheRegion，可选 <br />
第二行指定要使用的cacheRegion是myCacheRegion，即你可以给每个查询缓存做一个单独的配置，使用setCacheRegion来做这个指定，需要在ehcache.xml里面配置它： <br />
&lt;cache name="myCacheRegion" maxElementsInMemory="10" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="7200" overflowToDisk="true" /&gt; <br />
如果省略第二行，不设置cacheRegion的话，那么会使用上面提到的标准查询缓存的配置，也就是net.sf.hibernate.cache.StandardQueryCache</p>
<p>对于查询缓存来说，缓存的key是根据hql生成的sql，再加上参数，分页等信息（可以通过日志输出看到，不过它的输出不是很可读，最好改一下它的代码）。 <br />
比如hql： <br />
from Cat c where c.name like ? <br />
生成大致如下的sql： <br />
select * from cat c where c.name like ? <br />
参数是"tiger%"，那么查询缓存的key*大约*是这样的字符串（我是凭记忆写的，并不精确，不过看了也该明白了）： <br />
select * from cat c where c.name like ? , parameter:tiger% <br />
这样，保证了同样的查询、同样的参数等条件下具有一样的key。 <br />
现在说说缓存的value，如果是list方式的话，value在这里并不是整个结果集，而是查询出来的这一串ID。也就是说，不管是list方法还是iterate方法，第一次查询的时候，它们的查询方式很它们平时的方式是一样的，list执行一条sql，iterate执行1+N条，多出来的行为是它们填充了缓存。但是到同样条件第二次查询的时候，就都和iterate的行为一样了，根据缓存的key去缓存里面查到了value，value是一串id，然后在到class的缓存里面去一个一个的load出来。这样做是为了节约内存。 <br />
可以看出来，查询缓存需要打开相关类的class缓存。list和iterate方法第一次执行的时候，都是既填充查询缓存又填充class缓存的。 <br />
<strong>这里还有一个很容易被忽视的重要问题，即打开查询缓存以后，即使是list方法也可能遇到1+N的问题！</strong>相同条件第一次list的时候，因为查询缓存中找不到，不管class缓存是否存在数据，总是发送一条sql语句到数据库获取全部数据，然后填充查询缓存和class缓存。但是第二次执行的时候，问题就来了，如果你的class缓存的超时时间比较短，现在class缓存都超时了，但是查询缓存还在，那么list方法在获取id串以后，将会一个一个去数据库load！因此，class缓存的超时时间一定不能短于查询缓存设置的超时时间！如果还设置了发呆时间的话，保证class缓存的发呆时间也大于查询的缓存的生存时间。这里还有其他情况，比如class缓存被程序强制evict了，这种情况就请自己注意了。</p>
<p>另外，如果hql查询包含select字句，那么查询缓存里面的value就是整个结果集了。</p>
<p>当hibernate更新数据库的时候，它怎么知道更新哪些查询缓存呢？ <br />
hibernate在一个地方维护每个表的最后更新时间，其实也就是放在上面net.sf.hibernate.cache.UpdateTimestampsCache所指定的缓存配置里面。 <br />
当通过hibernate更新的时候，hibernate会知道这次更新影响了哪些表。然后它更新这些表的最后更新时间。每个缓存都有一个生成时间和这个缓存所查询的表，当hibernate查询一个缓存是否存在的时候，如果缓存存在，它还要取出缓存的生成时间和这个缓存所查询的表，然后去查找这些表的最后更新时间，如果有一个表在生成时间后更新过了，那么这个缓存是无效的。 <br />
可以看出，只要更新过一个表，那么凡是涉及到这个表的查询缓存就失效了，因此查询缓存的命中率可能会比较低。</p>
<p><strong>Collection缓存</strong> <br />
需要在hbm的collection里面设置 <br />
&lt;cache usage="read-write"/&gt; <br />
假如class是Cat，collection叫children，那么ehcache里面配置 <br />
&lt;cache name="com.xxx.pojo.Cat.children" <br />
maxElementsInMemory="20" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="7200" <br />
overflowToDisk="true" /&gt; <br />
Collection的缓存和前面查询缓存的list一样，也是只保持一串id，但它不会因为这个表更新过就失效，一个collection缓存仅在这个collection里面的元素有增删时才失效。 <br />
这样有一个问题，如果你的collection是根据某个字段排序的，当其中一个元素更新了该字段时，导致顺序改变时，collection缓存里面的顺序没有做更新。</p>
<p><strong>缓存策略</strong> <br />
只读缓存（read-only）：没有什么好说的 <br />
读/写缓存（read-write）:程序可能要的更新数据 <br />
不严格的读/写缓存（nonstrict-read-write）：需要更新数据，但是两个事务更新同一条记录的可能性很小，性能比读写缓存好 <br />
事务缓存（transactional）：缓存支持事务，发生异常的时候，缓存也能够回滚，只支持jta环境，这个我没有怎么研究过</p>
<p>读写缓存和不严格读写缓存在实现上的区别在于，读写缓存更新缓存的时候会把缓存里面的数据换成一个锁，其他事务如果去取相应的缓存数据，发现被锁住了，然后就直接取数据库查询。 <br />
在hibernate2.1的ehcache实现中，如果锁住部分缓存的事务发生了异常，那么缓存会一直被锁住，直到60秒后超时。 <br />
不严格读写缓存不锁定缓存中的数据。</p>
<p><strong>使用二级缓存的前置条件</strong> <br />
你的hibernate程序对数据库有独占的写访问权，其他的进程更新了数据库，hibernate是不可能知道的。你操作数据库必需直接通过hibernate，如果你调用存储过程，或者自己使用jdbc更新数据库，hibernate也是不知道的。hibernate3.0的大批量更新和删除是不更新二级缓存的，但是据说3.1已经解决了这个问题。 <br />
这个限制相当的棘手，有时候hibernate做批量更新、删除很慢，但是你却不能自己写jdbc来优化，很郁闷吧。 <br />
SessionFactory也提供了移除缓存的方法，你一定要自己写一些JDBC的话，可以调用这些方法移除缓存，这些方法是： <br />
void evict(Class persistentClass) <br />
Evict all entries from the second-level cache. <br />
void evict(Class persistentClass, Serializable id) <br />
Evict an entry from the second-level cache. <br />
void evictCollection(String roleName) <br />
Evict all entries from the second-level cache. <br />
void evictCollection(String roleName, Serializable id) <br />
Evict an entry from the second-level cache. <br />
void evictQueries() <br />
Evict any query result sets cached in the default query cache region. <br />
void evictQueries(String cacheRegion) <br />
Evict any query result sets cached in the named query cache region. <br />
不过我不建议这样做，因为这样很难维护。比如你现在用JDBC批量更新了某个表，有3个查询缓存会用到这个表，用evictQueries(String cacheRegion)移除了3个查询缓存，然后用evict(Class persistentClass)移除了class缓存，看上去好像完整了。不过哪天你添加了一个相关查询缓存，可能会忘记更新这里的移除代码。如果你的jdbc代码到处都是，在你添加一个查询缓存的时候，还知道其他什么地方也要做相应的改动吗？</p>
<p>----------------------------------------------------</p>
<p><strong>总结：</strong> <br />
不要想当然的以为缓存一定能提高性能，仅仅在你能够驾驭它并且条件合适的情况下才是这样的。hibernate的二级缓存限制还是比较多的，不方便用jdbc可能会大大的降低更新性能。在不了解原理的情况下乱用，可能会有1+N的问题。不当的使用还可能导致读出脏数据。 <br />
如果受不了hibernate的诸多限制，那么还是自己在应用程序的层面上做缓存吧。 <br />
在越高的层面上做缓存，效果就会越好。就好像尽管磁盘有缓存，数据库还是要实现自己的缓存，尽管数据库有缓存，咱们的应用程序还是要做缓存。因为底层的缓存它并不知道高层要用这些数据干什么，只能做的比较通用，而高层可以有针对性的实现缓存，所以在更高的级别上做缓存，效果也要好些吧。</p>
<p>终于写完了，好累&#8230;&#8230;</p>
<img src ="http://www.blogjava.net/LeungXin/aggbug/167290.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/LeungXin/" target="_blank">梁昕</a> 2007-12-12 18:02 <a href="http://www.blogjava.net/LeungXin/articles/167290.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用模板模式简化DAO操作Hibernate</title><link>http://www.blogjava.net/LeungXin/articles/151563.html</link><dc:creator>梁昕</dc:creator><author>梁昕</author><pubDate>Tue, 09 Oct 2007 14:41:00 GMT</pubDate><guid>http://www.blogjava.net/LeungXin/articles/151563.html</guid><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 相信使用过Spring ＋ Hibernate开发过的人，在写DAO的时候都使用过Spring的HibernateDaoSupport类，然后在实现的时候就可以很轻松的使用getHibernateTemplate()方法之后就可以调用save()、delete()、update()等Hibernate的Session的操作，很简单。比如：<br />
<p clear="both"></p>
<p class="code">getHibernateTemplate().save(user);</p>
<br />
　　这样一句话在我们没有Spring的时候就必须使用如下的代码才能完成：<br />
<p class="code">Session session = HibernateUtil.getSession();<br />
Transaction tx = session.beginTransaction();<br />
session.save(user);<br />
tx.commit();<br />
HibernateUtil.colseSession();</p>
<br />
　　这里还省去了异常处理，同时使用了HibernateUtil类来简化从SessionFactory获取Session，以及关闭Session等处理。<br />
<br />
　　但是我们在使用Hibernate的时候不一定会使用Spring，所以我们可以模仿Spring的处理方式，做一个Hibernate的模板，使用模板模式来简化我们的开发，其主要的目的就是为了简化开发，使代码达到最大话的重用。<br />
1． 我们现来实现一个Hibernate模板：<br />
<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><span style="color: #0000ff">package</span><span style="color: #000000">&nbsp;kick.hibernate;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;net.sf.hibernate.HibernateException;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;net.sf.hibernate.Session;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /></span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;net.sf.hibernate.Transaction;<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top"  alt="" /><br />
<img id="Codehighlighter1_170_590_Open_Image" onclick="this.style.display='none'; Codehighlighter1_170_590_Open_Text.style.display='none'; Codehighlighter1_170_590_Closed_Image.style.display='inline'; Codehighlighter1_170_590_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_170_590_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_170_590_Closed_Text.style.display='none'; Codehighlighter1_170_590_Open_Image.style.display='inline'; Codehighlighter1_170_590_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;HibernateTemplate</span><span id="Codehighlighter1_170_590_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_170_590_Open_Text"><span style="color: #000000">{<br />
<img id="Codehighlighter1_250_587_Open_Image" onclick="this.style.display='none'; Codehighlighter1_250_587_Open_Text.style.display='none'; Codehighlighter1_250_587_Closed_Image.style.display='inline'; Codehighlighter1_250_587_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_250_587_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_250_587_Closed_Text.style.display='none'; Codehighlighter1_250_587_Open_Image.style.display='inline'; Codehighlighter1_250_587_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">static</span><span style="color: #000000">&nbsp;Object&nbsp;run(HibernateCallback&nbsp;callback)&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;HibernateException</span><span id="Codehighlighter1_250_587_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_250_587_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />Session&nbsp;session&nbsp;</span><span style="color: #000000">=</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/InBlock.gif" align="top"  alt="" />Transaction&nbsp;tx&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">null</span><span style="color: #000000">;<br />
<img id="Codehighlighter1_303_475_Open_Image" onclick="this.style.display='none'; Codehighlighter1_303_475_Open_Text.style.display='none'; Codehighlighter1_303_475_Closed_Image.style.display='inline'; Codehighlighter1_303_475_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_303_475_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_303_475_Closed_Text.style.display='none'; Codehighlighter1_303_475_Open_Image.style.display='inline'; Codehighlighter1_303_475_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">try</span><span style="color: #000000">&nbsp;</span><span id="Codehighlighter1_303_475_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_303_475_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />session&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;HibernateSessionutil.currentSession();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />tx&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;session.beginTransaction();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />Object&nbsp;result&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;callback.execute(session);<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />tx.commit();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />session.flush();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;result;<br />
<img id="Codehighlighter1_506_536_Open_Image" onclick="this.style.display='none'; Codehighlighter1_506_536_Open_Text.style.display='none'; Codehighlighter1_506_536_Closed_Image.style.display='inline'; Codehighlighter1_506_536_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_506_536_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_506_536_Closed_Text.style.display='none'; Codehighlighter1_506_536_Open_Image.style.display='inline'; Codehighlighter1_506_536_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />}</span></span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">catch</span><span style="color: #000000">&nbsp;(HibernateException&nbsp;e)&nbsp;</span><span id="Codehighlighter1_506_536_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_506_536_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />tx.rollback();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></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 id="Codehighlighter1_546_585_Open_Image" onclick="this.style.display='none'; Codehighlighter1_546_585_Open_Text.style.display='none'; Codehighlighter1_546_585_Closed_Image.style.display='inline'; Codehighlighter1_546_585_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top"  alt="" /><img id="Codehighlighter1_546_585_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_546_585_Closed_Text.style.display='none'; Codehighlighter1_546_585_Open_Image.style.display='inline'; Codehighlighter1_546_585_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top"  alt="" />}</span></span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">finally</span><span style="color: #000000">&nbsp;</span><span id="Codehighlighter1_546_585_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_546_585_Open_Text"><span style="color: #000000">{<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" />HibernateSessionutil.closeSession();<br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top"  alt="" />}</span></span><span style="color: #000000"><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /><br />
<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top"  alt="" /></span></div>
</span><br />
　　这里类很简单，就是使用一个实现HibernateCallBack接口的一个回掉类，在调用的时候根据具体的需求实现HibernateCallBack类。<br />
<br />
　　2． 回掉接口HibernateCallBack：<br />
<p class="code">package kick.hibernate;<br />
<br />
import net.sf.hibernate.HibernateException;<br />
import net.sf.hibernate.Session;<br />
<br />
public interface HibernateCallBack {<br />
Object execute(Session session)throws HibernateException;<br />
}</p>
<br />
　　好了，到此为止我们就可以使用这个模板了，可以用如下的方式使用：<br />
<p class="code">HibernateTemplate.run(new HibernateCallback() {<br />
public Object execute(Session session) throws HibernateException {<br />
session.save(user);<br />
return null;<br />
}<br />
});</p>
<p><br />
　　看看，是不是省去了很多代码？<br />
<br />
　　不过这还没有达到想Spring里面那样简单，不要着急，&#8220;面包会有的&#8221;，我们会达到的。</p>
<p>3． 实现我们自己的HibernateSupport类<br />
　　从上面的代码可以看出，我们要自己实现HibernateCallback接口，而每次我们实现的时候又重复代码了。因此我们再抽象，讲这些实现放到我们的HibernateSupport类里面去。看看我们上面的代码就知道我们实现HibernateCallback接口的目的就是为了调用session.save()方法，即session的方法。代码如下：（点击查看<a href="http://www.pconline.com.cn/pcedu/empolder/gj/java/0509/acc/05-09-19-java.txt"><u><font color="#0000ff">附件</font></u></a>）<br />
<br />
　　4． 抽象RootDao：<br />
　　该类为抽象类，在实现自己的DAO类的时候继承该类。该类的有一个HibernateSupport的对象，在子类中使用getHibernateTemplate()方法就可以得到该对象，然后调用它对应的方法。实现代码如下：<br />
</p>
<p class="code">package kick.hibernate.dao;<br />
<br />
import net.sf.hibernate.Session;<br />
import kick.hibernate.HibernateTemplateImpl;<br />
<br />
public abstract class RootDao {<br />
private HibernateSupport temp = null;<br />
<br />
/**<br />
* @return Returns the temp.<br />
*/<br />
public HibernateTemplateImpl getHibernateTemplate(Session session) {<br />
return new HibernateSupport();<br />
}<br />
}</p>
<p><br />
<br />
　　5． 使用例子：<br />
　　定义一个自己的DAO类，实现代码如下：<br />
</p>
<p class="code">public class UserDaoImpl extends RootDao implements UserDaoInterface{<br />
public void saveUser(User user) throws KickException {<br />
getHibernateTemplate().saveOrUpdate(user); <br />
}<br />
&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;<br />
实现其他的方法<br />
&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;<br />
}<br />
</p>
<img src ="http://www.blogjava.net/LeungXin/aggbug/151563.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/LeungXin/" target="_blank">梁昕</a> 2007-10-09 22:41 <a href="http://www.blogjava.net/LeungXin/articles/151563.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>