📄 best-practices.html
字号:
way you can still use the same transaction strategy and underlying connection provider. 在系统中对性能要求很严格的一些部分,某些操作也许直接使用JDBC会更好。但是请先<span class="emphasis"><em>确认</em></span>这的确是一个瓶颈,并且不要想当然认为JDBC一定会更快。如果确实需要直接使用JDBC,那么最好打开一个Hibernate <tt class="literal">Session</tt> 然后从 <tt class="literal">Session</tt>获得connection,按照这种办法你仍然可以使用同样的transaction策略和底层的connection provider。 </p></dd><dt><span class="term">理解<tt class="literal">Session</tt>清洗( flushing)</span></dt><dd><p> Session会不时的向数据库同步持久化状态,如果这种操作进行的过于频繁,性能会受到一定的影响。有时候你可以通过禁止自动flushing,尽量最小化非必要的flushing操作,或者更进一步,在一个特定的transaction中改变查询和其它操作的顺序。 </p></dd><dt><span class="term">在三层结构中,考虑使用托管对象(detached object)</span></dt><dd><p> 当使用一个servlet / session bean 类型的架构的时候, 你可以把已加载的持久对象在session bean层和servlet / JSP 层之间来回传递。使用新的session来为每个请求服务,使用 <tt class="literal">Session.merge()</tt> 或者<tt class="literal">Session.saveOrUpdate()</tt>来与数据库同步。 </p></dd><dt><span class="term">在两层结构中,考虑使用长持久上下文(long persistence contexts).</span></dt><dd><p> 为了得到最佳的可伸缩性,数据库事务(Database Transaction)应该尽可能的短。但是,程序常常需要实现长时间运行的<span class="emphasis"><em>“应用程序事务(Application Transaction)”</em></span>,包含一个从用户的观点来看的原子操作。这个应用程序事务可能跨越多次从用户请求到得到反馈的循环。用脱管对象(与session脱离的对象)来实现应用程序事务是常见的。或者,尤其在两层结构中,把Hibernate Session从JDBC连接中脱离开,下次需要用的时候再连接上。绝不要把一个Session用在多个应用程序事务(Application Transaction)中,否则你的数据可能会过期失效。 </p></dd><dt><span class="term">不要把异常看成可恢复的</span></dt><dd><p> 这一点甚至比“最佳实践”还要重要,这是“必备常识”。当异常发生的时候,必须要回滚 <tt class="literal">Transaction</tt> ,关闭<tt class="literal">Session</tt>。如果你不这样做的话,Hibernate无法保证内存状态精确的反应持久状态。尤其不要使用<tt class="literal">Session.load()</tt>来判断一个给定标识符的对象实例在数据库中是否存在,应该使用<tt class="literal">Session.get()</tt>或者进行一次查询. </p></dd><dt><span class="term">对于关联优先考虑lazy fetching </span></dt><dd><p> 谨慎的使用主动抓取(eager fetching)。对于关联来说,若其目标是无法在第二级缓存中完全缓存所有实例的类,应该使用代理(proxies)与/或具有延迟加载属性的集合(lazy collections)。若目标是可以被缓存的,尤其是缓存的命中率非常高的情况下,应该使用<tt class="literal">lazy="false"</tt>,明确的禁止掉eager fetching。如果那些特殊的确实适合使用join fetch 的场合,请在查询中使用<tt class="literal">left join fetch</tt>。 </p></dd><dt><span class="term"> 使用<span class="emphasis"><em>open session in view</em></span>模式,或者执行严格的<span class="emphasis"><em>装配期(assembly phase)</em></span>策略来避免再次抓取数据带来的问题 </span></dt><dd><p> Hibernate让开发者们摆脱了繁琐的<span class="emphasis"><em>Data Transfer Objects</em></span> (DTO)。在传统的EJB结构中,DTO有双重作用:首先,他们解决了entity bean无法序列化的问题;其次,他们隐含地定义了一个装配期,在此期间,所有在view层需要用到的数据,都被抓取、集中到了DTO中,然后控制才被装到表示层。Hibernate终结了第一个作用。然而,除非你做好了在整个渲染过程中都维护一个打开的持久化上下文(session)的准备,你仍然需要一个装配期(想象一下,你的业务方法与你的表示层有严格的契约,数据总是被放置到托管对象中)。这并非是Hibernate的限制!这是实现安全的事务化数据访问的基本需求。 </p></dd><dt><span class="term">考虑把Hibernate代码从业务逻辑代码中抽象出来</span></dt><dd><p> 把Hibernate的数据存取代码隐藏到接口(interface)的后面,组合使用<span class="emphasis"><em>DAO</em></span>和<span class="emphasis"><em>Thread Local Session</em></span>模式。通过Hibernate的<tt class="literal">UserType</tt>,你甚至可以用硬编码的JDBC来持久化那些本该被Hibernate持久化的类。 (该建议更适用于规模足够大应用软件中,对于那些只有5张表的应用程序并不适合。) </p></dd><dt><span class="term">不要用怪异的连接映射</span></dt><dd><p> 多对多连接用得好的例子实际上相当少见。大多数时候你在“连接表”中需要保存额外的信息。这种情况下,用两个指向中介类的一对多的连接比较好。实际上,我们认为绝大多数的连接是一对多和多对一的,你应该谨慎使用其它连接风格,用之前问自己一句,是否真的必须这么做。 </p></dd><dt><span class="term">偏爱双向关联</span></dt><dd><p> 单向关联更加难于查询。在大型应用中,几乎所有的关联必须在查询中可以双向导航。 </p></dd></dl></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="example-mappings.html">上一页</a> </td><td width="20%" align="center"><a accesskey="u" href="index.html">上一级</a></td><td width="40%" align="right"> </td></tr><tr><td width="40%" align="left" valign="top">第 23 章 示例:复杂映射实例 </td><td width="20%" align="center"><a accesskey="h" href="index.html">起始页</a></td><td width="40%" align="right" valign="top"> </td></tr></table></div></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -