📄 performance.html
字号:
<html><head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Chapter 12. 性能提升(Improving Performance)</title><link rel="stylesheet" href="../styles/html.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.60.1"><link rel="home" href="index.html" title="HIBERNATE - 符合Java习惯的关系数据库持久化"><link rel="up" href="index.html" title="HIBERNATE - 符合Java习惯的关系数据库持久化"><link rel="previous" href="worked-example.html" title="Chapter 11. 实例(A Worked Example)"><link rel="next" href="collection-performance.html" title="Chapter 13. 理解集合类的性能(Understanding Collection Performance)"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter 12. 性能提升(Improving Performance)</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="worked-example.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="collection-performance.html">Next</a></td></tr></table><hr></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="performance"></a>Chapter 12. 性能提升(Improving Performance)</h2></div></div><div></div></div><p> 我们已经为您展示了如何在对集合持久化时使用延迟装载(lazy initialization)。对于通常的对象引用,使用CGLIB代理可以达到类似的效果。我们也提到过Hibernate在<tt class="literal">Session</tt>级别缓存持久化对象。还有更多先进的缓存策略,你可以为每一个类单独配置。 </p><p> 这一章里,我们来教你如何使用这些特性,在必要的时候得到高得多的性能。 </p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="performance-s4"></a>12.1. 用于延迟装载的代理</h2></div></div><div></div></div><p> Hibernate使用动态字节码增强技术来实现持久化对象的延迟装载代理(使用优秀的CGLIB库)。 </p><p> 映射文件为每一个类声明一个类或者接口作为代理接口。建议使用这个类自身: </p><pre class="programlisting"><class name="eg.Order" proxy="eg.Order"></pre><p> 运行时的代理应该是<tt class="literal">Order</tt>的子类。注意被代理的类必须实现一个默认的构造器,并且至少在包内可见。 </p><p> 在扩展这种方法来对应多形的类时,要注意一些细节,比如: </p><pre class="programlisting"><class name="eg.Cat" proxy="eg.Cat"> ...... <subclass name="eg.DomesticCat" proxy="eg.DomesticCat"> ..... </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>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -