📄 performance.html
字号:
</subclass></class></pre><p> 首先,<tt class="literal">Cat</tt>永远不能被强制转换为<tt class="literal">DomesticCat</tt>,即使实际上该实例就是一个<tt class="literal">DomesticCat</tt>实例。 </p><pre class="programlisting">Cat cat = (Cat) session.load(Cat.class, id); // instantiate a proxy (does not hit the db)if ( cat.isDomesticCat() ) { // hit the db to initialize the proxy DomesticCat dc = (DomesticCat) cat; // Error! ....}</pre><p> 其次,代理的<tt class="literal">==</tt>可能不再成立。 </p><pre class="programlisting">Cat cat = (Cat) session.load(Cat.class, id); // instantiate a Cat proxyDomesticCat dc = (DomesticCat) session.load(DomesticCat.class, id); // required new DomesticCat proxy!System.out.println(cat==dc); // false</pre><p> 虽然如此,这种情况并不像看上去得那么糟。虽然我们现在有两个不同的引用来指向不同的代理对象,实际上底层的实例应该是同一个对象: </p><pre class="programlisting">cat.setWeight(11.0); // hit the db to initialize the proxySystem.out.println( dc.getWeight() ); // 11.0</pre><p> 第三,你不能对<tt class="literal">final</tt>的类或者具有<tt class="literal">final</tt>方法的类使用CGLIB代理。 </p><p> 最后,假如你的持久化对象在实例化的时候需要某些资源(比如,在实例化方法或者默认构造方法中),这些资源也会被代理需要。代理类实际上是持久化类的子类。 </p><p> 这些问题都来源于Java的单根继承模型的天生限制。如果你希望避免这些问题,你的每个持久化类必须抽象出一个接口,声明商业逻辑方法。你应该在映射文件中指定这些接口,比如: </p><pre class="programlisting"><class name="eg.Cat" proxy="eg.ICat"> ...... <subclass name="eg.DomesticCat" proxy="eg.IDomesticCat"> ..... </subclass></class></pre><p> 这里<tt class="literal">Cat</tt>实现<tt class="literal">ICat</tt>接口,并且<tt class="literal">DomesticCat</tt>实现<tt class="literal">IDomesticCat</tt>接口。于是 <tt class="literal">load()</tt>或者<tt class="literal">iterate()</tt>就会返回<tt class="literal">Cat</tt>和<tt class="literal">DomesticCat</tt>的实例的代理。(注意<tt class="literal">find()</tt>不会返回代理。) </p><pre class="programlisting">ICat cat = (ICat) session.load(Cat.class, catid);Iterator iter = session.iterate("from cat in class eg.Cat where cat.name='fritz'");ICat fritz = (ICat) iter.next();</pre><p> 关系也是延迟装载的。这意味着你必须把任何属性声明为<tt class="literal">ICat</tt>类型,而非<tt class="literal">Cat</tt>。 </p><p> 某些特定操作<span class="emphasis"><em>不</em></span>需要初始化代理 </p><div class="itemizedlist"><ul type="disc" compact><li><p> <tt class="literal">equals()</tt>, 假如持久化类没有重载<tt class="literal">equals()</tt> </p></li><li><p> <tt class="literal">hashCode()</tt>, 假如持久化类没有重载<tt class="literal">hashCode()</tt> </p></li><li><p> 标识符的get方法 </p></li></ul></div><p> Hibernate会识别出重载了<tt class="literal">equals()</tt> 或者 <tt class="literal">hashCode()</tt>方法的持久化类。 </p><p> 在初始化代理的时候发生的异常会被包装成<tt class="literal">LazyInitializationException</tt>。 </p><p> 有时候我们需要保证在<tt class="literal">Session</tt>关闭前某个代理或者集合已经被初始化了。当然,我们总是可以通过调用<tt class="literal">cat.getSex()</tt>或者 <tt class="literal">cat.getKittens().size()</tt>之类的方法来确保这一点。但是这样程序可读性不佳,也不符合通常的代码规范。静态方法<tt class="literal">Hibernate.initialize()</tt>和<tt class="literal">Hibernate.isInitialized()</tt>给你的应用程序一个正常的途径来加载集合或代理。<tt class="literal">Hibernate.initialize(cat)</tt> 会强制初始化一个代理,<tt class="literal">cat</tt>,只要它的<tt class="literal">Session</tt>仍然打开。<tt class="literal">Hibernate.initialize( cat.getKittens() )</tt>对kittens的集合具有同样的功能。 </p></div><div class="sect1" lang="zh-cn"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="performance-cache"></a>14.3. 第二层缓存(The Second Level Cache)s</h2></div></div><div></div></div><p> Hibernate<tt class="literal">Session</tt>是事务级别的持久化数据缓存。再为每个类或者每个集合配置一个集群或者JVM级别(<tt class="literal">SessionFactory</tt>级别)的缓存也是有可能的。你甚至可以插入一个集群的缓存。要小心,缓存永远不会知道其他进程可能对持久化仓库(数据库)进行的修改(即使他们可能设定为经常对缓存的数据进行失效)。 </p><p> 默认情况下,Hibernate使用EHCache进行JVM级别的缓存。但是,对JCS的支持现在已经被废弃了,未来版本的Hibernate将会去掉它。通过<tt class="literal">hibernate.cache.provider_class</tt>属性,你也可以指定其他缓存,只要其实现了<tt class="literal">net.sf.hibernate.cache.CacheProvider</tt>接口。 </p><div class="table"><a name="d0e8649"></a><p class="title"><b>表 14.1. Cache Providers</b></p><table summary="Cache Providers" border="1"><colgroup><col align="left"><col align="left"><col align="left"><col align="left"><col align="left"></colgroup><thead><tr><th align="left">Cache</th><th align="left">Provider class</th><th align="left">Type</th><th align="left">Cluster Safe</th><th align="left">Query Cache Supported</th></tr></thead><tbody><tr><td align="left">Hashtable (not intended for production use)</td><td align="left"><tt class="literal">net.sf.hibernate.cache.HashtableCacheProvider</tt></td><td align="left">memory</td><td align="left"> </td><td align="left">yes</td></tr><tr><td align="left">EHCache</td><td align="left"><tt class="literal">net.sf.hibernate.cache.EhCacheProvider</tt></td><td align="left">memory, disk</td><td align="left"> </td><td align="left">yes</td></tr><tr><td align="left">OSCache</td><td align="left"><tt class="literal">net.sf.hibernate.cache.OSCacheProvider</tt></td><td align="left">memory, disk</td><td align="left"> </td><td align="left">yes</td></tr><tr><td align="left">SwarmCache</td><td align="left"><tt class="literal">net.sf.hibernate.cache.SwarmCacheProvider</tt></td><td align="left">clustered (ip multicast)</td><td align="left">yes (clustered invalidation)</td><td align="left"> </td></tr><tr><td align="left">JBoss TreeCache</td><td align="left"><tt class="literal">net.sf.hibernate.cache.TreeCacheProvider</tt></td><td align="left">clustered (ip multicast), transactional</td><td align="left">yes (replication)</td><td align="left"> </td></tr></tbody></table></div><div class="sect2" lang="zh-cn"><div class="titlepage"><div><div><h3 class="title"><a name="performance-cache-mapping"></a>14.3.1. 对映射(Mapping)缓冲</h3></div></div><div></div></div><p> 类或者集合映射的<tt class="literal"><cache></tt>元素可能有下列形式: </p><div class="programlistingco"><pre class="programlisting"><cache <span class="co">(1)</span> usage="transactional|read-write|nonstrict-read-write|read-only" /></pre><div class="calloutlist"><table border="0" summary="Callout list"><tr><td width="5%" valign="top" align="left">(1)</td><td valign="top" align="left"><p> <tt class="literal">usage</tt> 指定了缓存策略: <tt class="literal">transactional</tt>,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -