﻿<?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-kangdy-随笔分类-Hibernate</title><link>http://www.blogjava.net/kangdy/category/47811.html</link><description>我就像AK47里打出去的子弹。目标TMD永远在前方。我只能TMD拼命向前。</description><language>zh-cn</language><lastBuildDate>Thu, 03 Nov 2011 03:32:21 GMT</lastBuildDate><pubDate>Thu, 03 Nov 2011 03:32:21 GMT</pubDate><ttl>60</ttl><item><title>Hibernate 实体对象的生命周期汇总</title><link>http://www.blogjava.net/kangdy/archive/2011/02/14/344265.html</link><dc:creator>AK47</dc:creator><author>AK47</author><pubDate>Mon, 14 Feb 2011 06:26:00 GMT</pubDate><guid>http://www.blogjava.net/kangdy/archive/2011/02/14/344265.html</guid><wfw:comment>http://www.blogjava.net/kangdy/comments/344265.html</wfw:comment><comments>http://www.blogjava.net/kangdy/archive/2011/02/14/344265.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kangdy/comments/commentRss/344265.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kangdy/services/trackbacks/344265.html</trackback:ping><description><![CDATA[本帖汇总了网上几篇关于hibernate的生命周期的帖子。<br />
<br />
<fieldset><legend>转载：</legend>
<p>实体对象的生命周期在Hibernate应用中是一个很关键的概念,正确的理解实体对象的生命周期将对我们应用Hibernate做持久层设计起到很大的作用.而所谓的实体对象的生命周期就是指实体对象由产生到被GC回收的一段过程.在这过程中我们需要理解的就是实体对象生命周期中的三种状态.<br />
<br />
1. 自由状态(Transient)<br />
所谓的Transient状态,即实体对象在内存中自由存在,与数据库中的记录无关,通常是我们的J2EE中 VO,并没有被纳入Hibernate的实体管理容器.</p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; width: 98%; font-size: 13px;"><span style="color: #008080;">1</span><img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;Test&nbsp;test&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Test();<br />
</span><span style="color: #008080;">2</span><span style="color: #000000;"><img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;test.setName(</span><span style="color: #000000;">"</span><span style="color: #000000;">energykk</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
</span><span style="color: #008080;">3</span><span style="color: #000000;"><img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">此时的test对象处于Transient(自由状态)并没有被Hibernate框架所管理</span><span style="color: #008000;"><br />
</span><span style="color: #008080;">4</span><span style="color: #008000;"><img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div>
<br />
2.持久状态(Persistent)<br />
何谓 Persistent? 即实体对象已经处于被Hibernate实体管理容器容器所管理的状态.这种状态下这个实体对象的引用将被纳入Hibernate实体管理容器容器所管理.<br />
处于Persistent状态的实体对象,对它的变更也将被固化到数据库中.<br />
在J2EE中通常指的是一个PO.<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; width: 98%; font-size: 13px;"><img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000;">Transaction&nbsp;tr&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;session.beginTransaction();<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session.save(test);<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">此时的test对象已经处于Persistent(持久状态)它被Hibernate 纳入实体管理容器</span><span style="color: #008000;"><br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tr.commit();<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Transaction&nbsp;tr2&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;session.beginTransaction();<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;test.setName(</span><span style="color: #000000;">"</span><span style="color: #000000;">xukai</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">在这个事务中我们并没有显示的调用save()方法但是由于Persistent状态的对象将会自动的固化到<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">数据库中,因此此时正处在Persistent状态的test对象的变化也将自动被同步到数据库中</span><span style="color: #008000;"><br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tr2.commit();</span></div>
<p>处于Persistent状态的实体可以简单的理解为:如果一个实体对象与session发生了关联,并且处于session的有效期内,那么这个实体对象就处于Persistent状态.</p>
<p>3.游离状态(Detached)<br />
处于Persistent状态的实体对象,其对应的session关闭以后,那么这个实体就处于 Detached状态.<br />
我们可以认为session对象就是一个Persistent的宿主,一旦这个宿主失效,那么这个实体就处于 Detached状态.<br />
</p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; width: 98%; font-size: 13px;"><img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000;">session.close();<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">与test对象关联的session被关闭,因此此时的test对象进入 Detached(游离状态)</span><span style="color: #008000;"><br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session2&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;HibernateSessionFactory.getSession();<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Transaction&nbsp;tr3&nbsp;</span><span style="color: #000000;">=</span><span style="color: #000000;">&nbsp;session2.beginTransaction();<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session2.update(test);<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">此时正处于Detached状态的test对象由于再次借助与session2被纳入到Hibernate的实体管理容器所以此时的<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">test对象恢复到Persistent状态</span><span style="color: #008000;"><br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;test.setName(</span><span style="color: #000000;">"</span><span style="color: #000000;">jjjj</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tr3.commit();<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
<img alt="" src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session2.close();</span></div>
<br />
既然Transient状态的实体与Detached状态的实体都与Hibernate的实体管理容器没有关系,那他们到底存在哪些差异?<br />
差异就在于处于Transient状态的只有一个Name的属性.此时的test对象所包含的数据信息仅限于此,他与数据库中的记录没有任何瓜葛.<br />
但是处于Detached状态的实体已经不止包含Name这个属性,还被赋予了主键也就是通常POJO里的id属性,由于id是主键,他可以确定数据库表中的一条<br />
唯一的记录,那么自然的处于Detached状态的实体就能与数据库表中拥有相同id的记录相关联.<br />
这就是他们之间所存在的差异, 简而言之,Transient状态的实体缺乏与数据库表记录之间的联系,而Detached状态的试题恰恰相反.只不过是脱离了session这个数据库操作平台而已.</fieldset>原帖地址 ： <span style="color: #c0c0c0;"><u><a href="http://www.blogjava.net/energykk/archive/2007/05/08/115927.html">http://www.blogjava.net/energykk/archive/2007/05/08/115927.html</a><br />
</u></span><br />
&nbsp;生命周期图：<br />
原图地址：<span style="color: #c0c0c0;"><u><a href="http://hi.baidu.com/quest2run/blog/item/39e1d08c7dbd45f4503d9222.html">http://hi.baidu.com/quest2run/blog/item/39e1d08c7dbd45f4503d9222.html</a><br />
</u></span>&nbsp;<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/kangdy/11.jpg.png" border="0" /><br />
persistence context<br />
<br />
<img alt="" src="http://www.blogjava.net/images/blogjava_net/kangdy/22.jpg.png" border="0" /><br />
<br />
生命周期特征总结 ：<br />
原帖地址&nbsp;：<span style="color: #c0c0c0;">&nbsp;<u><a href="http://blog.csdn.net/hgd250/archive/2008/08/06/2775943.aspx">http://blog.csdn.net/hgd250/archive/2008/08/06/2775943.aspx</a><br />
</u></span><span><span><span><span style="color: #ccffcc;"><span style="color: #cc99ff;"><span style="color: #000000;"><span style="color: #000000;">Transient：</span> </span></span></span></span></span></span>
<p><span style="color: red;"><span><span><span><span style="color: #99ccff;"><span style="color: #ccffcc;"><span style="color: #cc99ff;"><span style="color: #000000;">&nbsp;&nbsp;&nbsp;<span style="color: #339966;">&nbsp;与数据库中的记录没有任何关系,即没有与其相关联的数据库记录.<br />
&nbsp;&nbsp;&nbsp;&nbsp;与session没有任何关系.即没有通过session对象的实例对其进行任何持久化的操作<br />
</span>Persistent：<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: red;"><span style="color: #339966;">每个persistent状态的实体对象都与一个session对象的实例相关联<br />
&nbsp;&nbsp;&nbsp;&nbsp;处于 Persistent状态的实体对象是与数据库中的记录相关联的.<br />
&nbsp;&nbsp;&nbsp;&nbsp;Hibernate会依据persistent状态的实体对象的属性变化而改变数据库中相对应的记录</span>.<br />
</span>Detached：<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #339966;">游离态是由持久态实体对象转变而来的.<br />
&nbsp;&nbsp;&nbsp;&nbsp;游离态实体不再与session对象相关联.<br />
&nbsp;&nbsp;&nbsp;&nbsp;游离态实体对象与数据库中的记录没有直接联系,对其所做的任何修改将不会影响到到数据库中的数据.<br />
&nbsp;&nbsp;&nbsp;&nbsp;游离态实体对象在数据库有相对应的数据记录,如果没有被其他事务删除.</span></span></span></span></span></span></span></span></span></p><img src ="http://www.blogjava.net/kangdy/aggbug/344265.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kangdy/" target="_blank">AK47</a> 2011-02-14 14:26 <a href="http://www.blogjava.net/kangdy/archive/2011/02/14/344265.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ThreadLocal 与 getCurrentSession</title><link>http://www.blogjava.net/kangdy/archive/2009/11/26/303772.html</link><dc:creator>AK47</dc:creator><author>AK47</author><pubDate>Thu, 26 Nov 2009 06:35:00 GMT</pubDate><guid>http://www.blogjava.net/kangdy/archive/2009/11/26/303772.html</guid><wfw:comment>http://www.blogjava.net/kangdy/comments/303772.html</wfw:comment><comments>http://www.blogjava.net/kangdy/archive/2009/11/26/303772.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kangdy/comments/commentRss/303772.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kangdy/services/trackbacks/303772.html</trackback:ping><description><![CDATA[<p>看了下面的文章才彻底明白了ThreadLocal 与 getCurrentSession的关系<br />
<a href="http://hi.baidu.com/%B7%C7%D4%C2%CE%DE%D0%C4/blog/item/8b14b8db49b40961d1164e54.html">http://hi.baidu.com/%B7%C7%D4%C2%CE%DE%D0%C4/blog/item/8b14b8db49b40961d1164e54.html</a><br />
</p>
<fieldset><legend>引用 :</legend>
<p>1 getCurrentSession创建的session会和绑定到当前线程,而openSession不会。</p>
<p>2 getCurrentSession创建的线程会在事务回滚或事物提交后自动关闭,而openSession必须手动关闭</p>
<p>这里getCurrentSession本地事务(本地事务:jdbc)时 要在配置文件里进行如下设置</p>
<p>&nbsp;* 如果使用的是本地事务（jdbc事务）<br />
&nbsp;&lt;property name="hibernate.current_session_context_class"&gt;thread&lt;/property&gt;<br />
&nbsp;* 如果使用的是全局事务（jta事务）<br />
&nbsp;&lt;property name="hibernate.current_session_context_class"&gt;jta&lt;/property&gt; </p>
<p>getCurrentSession () 使用当前的session<br />
openSession()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 重新建立一个新的session</p>
<p>在一个应用程序中，如果DAO 层使用Spring 的hibernate 模板，通过Spring 来控制session 的生命周期，则首选getCurrentSession ()。</p>
<p>使用Hibernate的大多数应用程序需要某种形式的&#8220;上下文相关的&#8221; session，特定的session在整个特定的上下文范围内始终有效。然而，对不同类型的应用程序而言，要为什么是组成这种&#8220;上下文&#8221;下一个定义通常是困难的；不同的上下文对&#8220;当前&#8221;这个概念定义了不同的范围。<span style="color: #ff0000;">在3.0版本之前，使用Hibernate的程序要么采用自行编写的基于 ThreadLocal的上下文session，要么采用HibernateUtil这样的辅助类，要么采用第三方框架（比如Spring或Pico)，它们提供了基于代理(proxy)或者基于拦截器(interception)的上下文相关session。</span><span style="color: #ff0000;">从3.0.1版本开始，Hibernate增加了SessionFactory.getCurrentSession()方法。</span>一开始，它假定了采用JTA事务，JTA事务定义了当前session的范围和上下文(scope and context)。Hibernate开发团队坚信，因为有好几个独立的JTA TransactionManager实现稳定可用，不论是否被部署到一个J2EE容器中，大多数(假若不是所有的）应用程序都应该采用JTA事务管理。基于这一点，采用JTA的上下文相关session可以满足你一切需要。</p>
<p>更好的是，从3.1开始，SessionFactory.getCurrentSession()的后台实现是可拔插的。因此，我们引入了新的扩展接口 (org.hibernate.context.CurrentSessionContext)和新的配置参数 (hibernate.current_session_context_class)，以便对什么是&#8220;当前session&#8221;的范围和上下文(scope and context)的定义进行拔插。</p>
<p>请参阅 org.hibernate.context.CurrentSessionContext接口的Javadoc,那里有关于它的契约的详细讨论。它定义了单一的方法，currentSession()，特定的实现用它来负责跟踪当前的上下文session。Hibernate内置了此接口的两种实现。</p>
<p>org.hibernate.context.JTASessionContext - 当前session根据JTA来跟踪和界定。这和以前的仅支持JTA的方法是完全一样的。详情请参阅Javadoc。</p>
<p>org.hibernate.context.ThreadLocalSessionContext - 当前session通过当前执行的线程来跟踪和界定。详情也请参阅Javadoc。</p>
<p>这两种实现都提供了&#8220;每数据库事务对应一个session&#8221;的编程模型，也称作每次请求一个session。Hibernate session的起始和终结由数据库事务的生存来控制。假若你采用自行编写代码来管理事务（比如，在纯粹的J2SE,或者 JTA/UserTransaction/BMT），建议你使用Hibernate Transaction API来把底层事务实现从你的代码中隐藏掉。如果你在支持CMT的EJB容器中执行，事务边界是声明式定义的，你不需要在代码中进行任何事务或 session管理操作。请参阅第 11 章 事务和并发一节来阅读更多的内容和示例代码。</p>
<p>hibernate.current_session_context_class 配置参数定义了应该采用哪个org.hibernate.context.CurrentSessionContext实现。注意，为了向下兼容，如果未配置此参数，但是存在org.hibernate.transaction.TransactionManagerLookup的配置，Hibernate会采用org.hibernate.context.JTASessionContext。一般而言，此参数的值指明了要使用的实现类的全名，但那两个内置的实现可以使用简写，即"jta"和"thread"。</p>
<p>1、getCurrentSession()与openSession()的区别？</p>
<p>* 采用getCurrentSession()创建的session会绑定到当前线程中，而采用openSession()<br />
创建的session则不会<br />
* 采用getCurrentSession()创建的session在commit或rollback时会自动关闭，而采用openSession()<br />
创建的session必须手动关闭<br />
2、使用getCurrentSession()需要在hibernate.cfg.xml文件中加入如下配置：<br />
* 如果使用的是本地事务（jdbc事务）<br />
&lt;property name="hibernate.current_session_context_class"&gt;thread&lt;/property&gt;<br />
* 如果使用的是全局事务（jta事务）<br />
&lt;property name="hibernate.current_session_context_class"&gt;jta&lt;/property&gt;</p>
<p>利于ThreadLocal模式管理Session<br />
&nbsp;&nbsp; 早在Java1.2推出之时，Java平台中就引入了一个新的支持：java.lang.ThreadLocal，给我们在编写多线程程序<br />
&nbsp;&nbsp; 时提供了一种新的选择。ThreadLocal是什么呢？其实ThreadLocal并非是一个线程的本地实现版本，它并不是一个Thread，<br />
&nbsp;&nbsp; 而是thread local variable(线程局部变量)。也许把它命名为ThreadLocalVar更加合适。线程局部变量(ThreadLocal)<br />
&nbsp;&nbsp; 其实的功用非常简单，就是为每一个使用某变量的线程都提供一个该变量值的副本，是每一个线程都可以独立地改变自己的副本，<br />
&nbsp;&nbsp; 而不会和其它线程的副本冲突。从线程的角度看，就好像每一个线程都完全拥有一个该变量。<br />
&nbsp;&nbsp; ThreadLocal是如何做到为每一个线程维护变量的副本的呢？其实实现的思路很简单，在ThreadLocal类中有一个Map，<br />
&nbsp;&nbsp; 用于存储每一个线程的变量的副本。比如下面的示例实现(为了简单，没有考虑集合的泛型)：<br />
public class HibernateUtil {</p>
<p>public static final ThreadLocal session =new ThreadLocal();</p>
<p>public static final SessionFactory sessionFactory;<br />
&nbsp;&nbsp; static {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sessionFactory = new Configuration().configure().buildSessionFactory();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (Throwable ex) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new ExceptionInInitializerError(ex);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; public static Session currentSession() throws HibernateException {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Session s = session.get();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(s == null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s = sessionFactory.openSession();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session.set(s);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return s;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public static void closeSession() throws HibernateException {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Session s = session.get();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(s != null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session.set(null);<br />
&nbsp;&nbsp;&nbsp; }<br />
}</p>
</fieldset>
<p>原来一切都是那么简单。<br />
</p><img src ="http://www.blogjava.net/kangdy/aggbug/303772.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kangdy/" target="_blank">AK47</a> 2009-11-26 14:35 <a href="http://www.blogjava.net/kangdy/archive/2009/11/26/303772.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate的缓存机制</title><link>http://www.blogjava.net/kangdy/archive/2009/11/18/302794.html</link><dc:creator>AK47</dc:creator><author>AK47</author><pubDate>Wed, 18 Nov 2009 06:12:00 GMT</pubDate><guid>http://www.blogjava.net/kangdy/archive/2009/11/18/302794.html</guid><wfw:comment>http://www.blogjava.net/kangdy/comments/302794.html</wfw:comment><comments>http://www.blogjava.net/kangdy/archive/2009/11/18/302794.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kangdy/comments/commentRss/302794.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kangdy/services/trackbacks/302794.html</trackback:ping><description><![CDATA[网上找到一些关于hibernate缓存的文章,个人觉得很不错.整合了一下.<br />
<a href="http://www.javaresearch.org/article/53556.htm">http://www.javaresearch.org/article/53556.htm</a>&nbsp; Hibernate的缓存机制<br />
<fieldset><legend>引用 :</legend>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;缓存是介于应用程序和物理数据源之间，其作用是为了降低应用程序对物理数据源访问的频次，从而提高了应用的运行性能。缓存内的数据是对物理数据源中的数据的复制，应用程序在运行时从缓存读写数据，在特定的时刻或事件会同步缓存和物理数据源的数据。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 缓存的介质一般是内存，所以读写速度很快。但如果缓存中存放的数据量非常大时，也会用硬盘作为缓存介质。缓存的实现不仅仅要考虑存储的介质，还要考虑到管理缓存的并发访问和缓存数据的生命周期。<br />
<br />
Hibernate的缓存包括Session的缓存和SessionFactory的缓存，其中SessionFactory的缓存又可以分为两类：内置缓存和外置缓存。Session的缓存是内置的，不能被卸载，也被称为Hibernate的第一级缓存。SessionFactory的内置缓存和 Session的缓存在实现方式上比较相似，前者是SessionFactory对象的一些集合属性包含的数据，后者是指Session的一些集合属性包含的数据。SessionFactory的内置缓存中存放了映射元数据和预定义SQL语句，映射元数据是映射文件中数据的拷贝，而预定义SQL语句是在 Hibernate初始化阶段根据映射元数据推导出来，SessionFactory的内置缓存是只读的，应用程序不能修改缓存中的映射元数据和预定义 SQL语句，因此SessionFactory不需要进行内置缓存与映射文件的同步。SessionFactory的外置缓存是一个可配置的插件。在默认情况下，SessionFactory不会启用这个插件。外置缓存的数据是数据库数据的拷贝，外置缓存的介质可以是内存或者硬盘。 SessionFactory的外置缓存也被称为Hibernate的第二级缓存。<br />
<br />
Hibernate的这两级缓存都位于持久化层，存放的都是数据库数据的拷贝，那么它们之间的区别是什么呢？为了理解二者的区别，需要深入理解持久化层的缓存的两个特性：缓存的范围和缓存的并发访问策略。<br />
<br />
持久化层的缓存的范围<br />
<br />
缓存的范围决定了缓存的生命周期以及可以被谁访问。缓存的范围分为三类。<br />
<br />
1&nbsp;事务范围：缓存只能被当前事务访问。缓存的生命周期依赖于事务的生命周期，当事务结束时，缓存也就结束生命周期。在此范围下，缓存的介质是内存。事务可以是数据库事务或者应用事务，每个事务都有独自的缓存，缓存内的数据通常采用相互关联的的对象形式。<br />
<br />
2&nbsp;进程范围：缓存被进程内的所有事务共享。这些事务有可能是并发访问缓存，因此必须对缓存采取必要的事务隔离机制。缓存的生命周期依赖于进程的生命周期，进程结束时，缓存也就结束了生命周期。进程范围的缓存可能会存放大量的数据，所以存放的介质可以是内存或硬盘。缓存内的数据既可以是相互关联的对象形式也可以是对象的松散数据形式。松散的对象数据形式有点类似于对象的序列化数据，但是对象分解为松散的算法比对象序列化的算法要求更快。<br />
<br />
3&nbsp;集群范围：在集群环境中，缓存被一个机器或者多个机器的进程共享。缓存中的数据被复制到集群环境中的每个进程节点，进程间通过远程通信来保证缓存中的数据的一致性，缓存中的数据通常采用对象的松散数据形式。<br />
<br />
对大多数应用来说，应该慎重地考虑是否需要使用集群范围的缓存，因为访问的速度不一定会比直接访问数据库数据的速度快多少。<br />
<br />
持久化层可以提供多种范围的缓存。如果在事务范围的缓存中没有查到相应的数据，还可以到进程范围或集群范围的缓存内查询，如果还是没有查到，那么只有到数据库中查询。事务范围的缓存是持久化层的第一级缓存，通常它是必需的；进程范围或集群范围的缓存是持久化层的第二级缓存，通常是可选的。<br />
<br />
持久化层的缓存的并发访问策略<br />
<br />
当多个并发的事务同时访问持久化层的缓存的相同数据时，会引起并发问题，必须采用必要的事务隔离措施。<br />
<br />
在进程范围或集群范围的缓存，即第二级缓存，会出现并发问题。因此可以设定以下四种类型的并发访问策略，每一种策略对应一种事务隔离级别。<br />
<br />
事务型：仅仅在受管理环境中适用。它提供了Repeatable&nbsp;Read事务隔离级别。对于经常被读但很少修改的数据，可以采用这种隔离类型，因为它可以防止脏读和不可重复读这类的并发问题。<br />
<br />
读写型：提供了Read&nbsp;Committed事务隔离级别。仅仅在非集群的环境中适用。对于经常被读但很少修改的数据，可以采用这种隔离类型，因为它可以防止脏读这类的并发问题。<br />
<br />
非严格读写型：不保证缓存与数据库中数据的一致性。如果存在两个事务同时访问缓存中相同数据的可能，必须为该数据配置一个很短的数据过期时间，从而尽量避免脏读。对于极少被修改，并且允许偶尔脏读的数据，可以采用这种并发访问策略。&nbsp;　　只读型：对于从来不会修改的数据，如参考数据，可以使用这种并发访问策略。<br />
<br />
事务型并发访问策略是事务隔离级别最高，只读型的隔离级别最低。事务隔离级别越高，并发性能就越低。<br />
<br />
什么样的数据适合存放到第二级缓存中？<br />
<br />
1、很少被修改的数据&nbsp;<br />
<br />
2、不是很重要的数据，允许出现偶尔并发的数据<br />
<br />
3、不会被并发访问的数据<br />
<br />
4、参考数据<br />
<br />
不适合存放到第二级缓存的数据？<br />
<br />
1、经常被修改的数据<br />
<br />
2、财务数据，绝对不允许出现并发<br />
<br />
3、与其他应用共享的数据。<br />
<br />
Hibernate的二级缓存<br />
<br />
如前所述，Hibernate提供了两级缓存，第一级是Session的缓存。由于Session对象的生命周期通常对应一个数据库事务或者一个应用事务，因此它的缓存是事务范围的缓存。第一级缓存是必需的，不允许而且事实上也无法比卸除。在第一级缓存中，持久化类的每个实例都具有唯一的OID。<br />
<br />
第二级缓存是一个可插拔的的缓存插件，它是由SessionFactory负责管理。由于SessionFactory对象的生命周期和应用程序的整个过程对应，因此第二级缓存是进程范围或者集群范围的缓存。这个缓存中存放的对象的松散数据。第二级对象有可能出现并发问题，因此需要采用适当的并发访问策略，该策略为被缓存的数据提供了事务隔离级别。缓存适配器用于把具体的缓存实现软件与Hibernate集成。第二级缓存是可选的，可以在每个类或每个集合的粒度上配置第二级缓存。<br />
<br />
Hibernate的二级缓存策略的一般过程如下：<br />
<br />
1)&nbsp;条件查询的时候，总是发出一条select&nbsp;*&nbsp;from&nbsp;table_name&nbsp;where&nbsp;&#8230;.&nbsp;（选择所有字段）这样的SQL语句查询数据库，一次获得所有的数据对象。&nbsp;<br />
<br />
2)&nbsp;把获得的所有数据对象根据ID放入到第二级缓存中。&nbsp;<br />
<br />
3)&nbsp;当Hibernate根据ID访问数据对象的时候，首先从Session一级缓存中查；查不到，如果配置了二级缓存，那么从二级缓存中查；查不到，再查询数据库，把结果按照ID放入到缓存。&nbsp;<br />
<br />
4)&nbsp;删除、更新、增加数据的时候，同时更新缓存。<br />
<br />
Hibernate的二级缓存策略，是针对于ID查询的缓存策略，对于条件查询则毫无作用。为此，Hibernate提供了针对条件查询的Query缓存。<br />
<br />
Hibernate的Query缓存策略的过程如下：&nbsp;<br />
<br />
1)&nbsp;Hibernate首先根据这些信息组成一个Query&nbsp;Key，Query&nbsp;Key包括条件查询的请求一般信息：SQL,&nbsp;SQL需要的参数，记录范围（起始位置rowStart，最大记录个数maxRows)，等。&nbsp;<br />
<br />
2)&nbsp;Hibernate根据这个Query&nbsp;Key到Query缓存中查找对应的结果列表。如果存在，那么返回这个结果列表；如果不存在，查询数据库，获取结果列表，把整个结果列表根据Query&nbsp;Key放入到Query缓存中。&nbsp;<br />
<br />
3)&nbsp;Query&nbsp;Key中的SQL涉及到一些表名，如果这些表的任何数据发生修改、删除、增加等操作，这些相关的Query&nbsp;Key都要从缓存中清空 </fieldset><br />
<a href="http://www.javaeye.com/topic/249465">http://www.javaeye.com/topic/249465</a> Hibernate缓存机制<br />
<br />
<fieldset><legend>引用 :</legend><span style="color: red;">&nbsp; <span class="hilite1">Hibernate</span>的缓存管理</span> <br />
<br />
<span style="color: blue;">&nbsp; 一级缓存的管理:</span> <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: red;">evit(Object obj)</span>&nbsp; 将指定的持久化对象从一级缓存中清除,释放对象所占用的内存资源,指定对象从持久化状态变为脱管状态,从而成为游离对象. <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: red;">clear()</span>&nbsp; 将一级缓存中的所有持久化对象清除,释放其占用的内存资源 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: red;">contains(Object obj) </span>判断指定的对象是否存在于一级缓存中. <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: red;">flush() </span>刷新一级缓存区的内容,使之与数据库数据保持同步. <br />
<br />
&nbsp; <span style="color: blue;">二级缓存的管理:</span>&nbsp;<br />
&nbsp;&nbsp;&nbsp;<br />
<span style="color: red;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; evict(Class arg0, Serializable arg1)</span>&nbsp; 将某个类的指定ID的持久化对象从二级缓存中清除,释放对象所占用的资源. <br />
<br />
<span class="hilite1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Hibernate</span>的二级缓存功能是靠配置二级缓存插件来实现的,<span class="hilite1">Hibernate</span>为了集成这些插件,<span class="hilite1">Hibernate</span>提供了org.<span class="hilite1">hibernate</span>.cache.CacheProvider借口,它充当缓存插件与<span class="hilite1">Hibernate</span>之间的适配器 . <br />
<br />
常用的二级缓存插件 <br />
EHCache&nbsp; org.<span class="hilite1">hibernate</span>.cache.EhCacheProvider <br />
OSCache&nbsp; org.<span class="hilite1">hibernate</span>.cache.OSCacheProvider <br />
SwarmCahe&nbsp; org.<span class="hilite1">hibernate</span>.cache.SwarmCacheProvider <br />
JBossCache&nbsp; org.<span class="hilite1">hibernate</span>.cache.TreeCacheProvider <br />
<br />
简单介绍一下EHCache的配置<br />
hibernate.cfg.xml<br />
<fieldset><legend>Xml代码: </legend>&lt;hibernate-configuration&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;session-factory&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;!-- 设置二级缓存插件EHCache的Provider类--&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="hibernate.cache.provider_class"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.hibernate.cache.EhCacheProvider<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;!-- 启动"查询缓存" --&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="hibernate.cache.use_query_cache"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; true<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/session-factory&gt;<br />
&nbsp; &lt;/hibernate-configuration&gt;</fieldset>ehcache.xml<br />
<fieldset><legend>Xml代码:</legend>&lt;ehcache&gt;<br />
&nbsp; &lt;!-- maxElementsInMemory为缓存对象的最大数目, eternal设置是否永远不过期,timeToIdleSeconds对象处于空闲状态的最多秒数,timeToLiveSeconds对象处于缓存状态的最多秒数 --&gt;<br />
&nbsp; &lt;diskStore path="java.io.tmpdir"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;defaultCache maxElementsInMemory="10000" eternal="false"&nbsp; timeToIdleSeconds="300" timeToLiveSeconds="600" overflowToDisk="true"/&gt;<br />
&lt;/ehcache&gt;</fieldset>****.hbm.xml<br />
<fieldset><legend>Xml代码:</legend>
<p>&lt;?xml version="1.0" encoding='UTF-8'?&gt;<br />
&lt;!DOCTYPE hibernate-mapping PUBLIC<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "-//Hibernate/Hibernate Mapping DTD 3.0//EN"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" &gt;</p>
<p>&lt;hibernate-mapping&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; &lt;class&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;!-- 设置该持久化类的二级缓存并发访问策略 read-only read-write nonstrict-read-write transactional--&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;cache usage="read-write"/&gt;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; &lt;/class&gt;</p>
<p>&lt;/hibernate-mapping&gt;</p>
</fieldset><br />
</fieldset><br />
<img src ="http://www.blogjava.net/kangdy/aggbug/302794.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kangdy/" target="_blank">AK47</a> 2009-11-18 14:12 <a href="http://www.blogjava.net/kangdy/archive/2009/11/18/302794.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>