[hibernate-commits] Hibernate SVN: r10744 - in trunk/Hibernate3/doc/reference/zh-cn: . modules

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Tue Nov 7 00:58:41 EST 2006


Author: caoxg
Date: 2006-11-07 00:58:20 -0500 (Tue, 07 Nov 2006)
New Revision: 10744

Modified:
   trunk/Hibernate3/doc/reference/zh-cn/master.xml
   trunk/Hibernate3/doc/reference/zh-cn/modules/architecture.xml
   trunk/Hibernate3/doc/reference/zh-cn/modules/basic_mapping.xml
   trunk/Hibernate3/doc/reference/zh-cn/modules/batch.xml
   trunk/Hibernate3/doc/reference/zh-cn/modules/configuration.xml
   trunk/Hibernate3/doc/reference/zh-cn/modules/filters.xml
   trunk/Hibernate3/doc/reference/zh-cn/modules/performance.xml
   trunk/Hibernate3/doc/reference/zh-cn/modules/persistent_classes.xml
   trunk/Hibernate3/doc/reference/zh-cn/modules/query_hql.xml
   trunk/Hibernate3/doc/reference/zh-cn/modules/query_sql.xml
   trunk/Hibernate3/doc/reference/zh-cn/modules/session_api.xml
   trunk/Hibernate3/doc/reference/zh-cn/modules/tutorial.xml
Log:
version 3.2 of Reference Chinese Version

Modified: trunk/Hibernate3/doc/reference/zh-cn/master.xml
===================================================================
--- trunk/Hibernate3/doc/reference/zh-cn/master.xml	2006-11-07 01:16:53 UTC (rev 10743)
+++ trunk/Hibernate3/doc/reference/zh-cn/master.xml	2006-11-07 05:58:20 UTC (rev 10744)
@@ -35,7 +35,7 @@
         <title>HIBERNATE - 符合Java习惯的关系数据库持久化</title>
         
         <subtitle>Hibernate参考文档</subtitle>
-        <releaseinfo>3.1.2</releaseinfo>
+        <releaseinfo>3.2</releaseinfo>
     </bookinfo>
 
     <toc/>

Modified: trunk/Hibernate3/doc/reference/zh-cn/modules/architecture.xml
===================================================================
--- trunk/Hibernate3/doc/reference/zh-cn/modules/architecture.xml	2006-11-07 01:16:53 UTC (rev 10743)
+++ trunk/Hibernate3/doc/reference/zh-cn/modules/architecture.xml	2006-11-07 05:58:20 UTC (rev 10744)
@@ -235,7 +235,7 @@
             请注意,Hibernate对JCA的支持,仍处于实验性阶段。
         </para>
     </sect1>
-    <sect1 id="architecture-current-session" revision="1">
+    <sect1 id="architecture-current-session" revision="2">
         <title>上下文相关的(Contextual)Session</title>
         <para>
            	使用Hibernate的大多数应用程序需要某种形式的“上下文相关的” session,特定的session在整个特定的上下文范围内始终有效。然而,对不同类型的应用程序而言,要为什么是组成这种“上下文”下一个定义通常是困难的;不同的上下文对“当前”这个概念定义了不同的范围。在3.0版本之前,使用Hibernate的程序要么采用自行编写的基于<literal>ThreadLocal</literal>的上下文session,要么采用<literal>HibernateUtil</literal>这样的辅助类,要么采用第三方框架(比如Spring或Pico),它们提供了基于代理(proxy)或者基于拦截器(interception)的上下文相关session。
@@ -247,7 +247,7 @@
             更好的是,从3.1开始,<literal>SessionFactory.getCurrentSession()</literal>的后台实现是可拔插的。因此,我们引入了新的扩展接口(<literal>org.hibernate.context.CurrentSessionContext</literal>)和新的配置参数(<literal>hibernate.current_session_context_class</literal>),以便对什么是“当前session”的范围和上下文(scope and context)的定义进行拔插。
         </para>
         <para>
-            请参阅<literal>org.hibernate.context.CurrentSessionContext</literal>接口的Javadoc,那里有关于它的契约的详细讨论。它定义了单一的方法,<literal>currentSession()</literal>,特定的实现用它来负责跟踪当前的上下文session。Hibernate内置了此接口的两种实现。
+            请参阅<literal>org.hibernate.context.CurrentSessionContext</literal>接口的Javadoc,那里有关于它的契约的详细讨论。它定义了单一的方法,<literal>currentSession()</literal>,特定的实现用它来负责跟踪当前的上下文session。Hibernate内置了此接口的三种实现。
         </para>
 
         <itemizedlist>
@@ -261,14 +261,19 @@
                     <literal>org.hibernate.context.ThreadLocalSessionContext</literal> - 当前session通过当前执行的线程来跟踪和界定。详情也请参阅Javadoc。
                 </para>
             </listitem>
+            <listitem>
+                <para>
+                    <literal>org.hibernate.context.ManagedSessionContext</literal> - 当前session通过当前执行的线程来跟踪和界定。但是,你需要负责使用这个类的静态方法将<literal>Session</literal>实例绑定、或者取消绑定,它并不会打开(open)、flush或者关闭(close)任何<literal>Session</literal>。
+                </para>
+            </listitem>
         </itemizedlist>
 
         <para>
-            这两种实现都提供了“每数据库事务对应一个session”的编程模型,也称作<emphasis>每次请求一个session</emphasis>。Hibernate session的起始和终结由数据库事务的生存来控制。假若你采用自行编写代码来管理事务(比如,在纯粹的J2SE,或者JTA/UserTransaction/BMT),建议你使用Hibernate <literal>Transaction</literal> API来把底层事务实现从你的代码中隐藏掉。如果你在支持CMT的EJB容器中执行,事务边界是声明式定义的,你不需要在代码中进行任何事务或session管理操作。请参阅<xref linkend="transactions"/>一节来阅读更多的内容和示例代码。
+            前两种实现都提供了“每数据库事务对应一个session”的编程模型,也称作<emphasis>每次请求一个session</emphasis>。Hibernate session的起始和终结由数据库事务的生存来控制。假若你在纯粹的 Java SE之上采用自行编写代码来管理事务,而不使用JTA,建议你使用Hibernate <literal>Transaction</literal> API来把底层事务实现从你的代码中隐藏掉。如果你使用JTA,请使用JTA借口来管理Transaction。如果你在支持CMT的EJB容器中执行代码,事务边界是声明式定义的,你不需要在代码中进行任何事务或session管理操作。请参阅<xref linkend="transactions"/>一节来阅读更多的内容和示例代码。
         </para>
 
         <para>
-            <literal>hibernate.current_session_context_class</literal>配置参数定义了应该采用哪个<literal>org.hibernate.context.CurrentSessionContext</literal>实现。注意,为了向下兼容,如果未配置此参数,但是存在<literal>org.hibernate.transaction.TransactionManagerLookup</literal>的配置,Hibernate会采用<literal>org.hibernate.context.JTASessionContext</literal>。一般而言,此参数的值指明了要使用的实现类的全名,但那两个内置的实现可以使用简写,即"jta"和"thread"。
+            <literal>hibernate.current_session_context_class</literal>配置参数定义了应该采用哪个<literal>org.hibernate.context.CurrentSessionContext</literal>实现。注意,为了向下兼容,如果未配置此参数,但是存在<literal>org.hibernate.transaction.TransactionManagerLookup</literal>的配置,Hibernate会采用<literal>org.hibernate.context.JTASessionContext</literal>。一般而言,此参数的值指明了要使用的实现类的全名,但那三种内置的实现可以使用简写,即"jta"、"thread"和"managed"。
             
         </para>
         

Modified: trunk/Hibernate3/doc/reference/zh-cn/modules/basic_mapping.xml
===================================================================
--- trunk/Hibernate3/doc/reference/zh-cn/modules/basic_mapping.xml	2006-11-07 01:16:53 UTC (rev 10743)
+++ trunk/Hibernate3/doc/reference/zh-cn/modules/basic_mapping.xml	2006-11-07 05:58:20 UTC (rev 10744)
@@ -93,7 +93,7 @@
 
 
 
-        <sect2 id="mapping-declaration-doctype" revision="2">
+        <sect2 id="mapping-declaration-doctype" revision="3">
             <title>Doctype</title>
 
             <para>
@@ -102,6 +102,53 @@
                 或<literal>hibernate.jar</literal>文件中找到。Hibernate总是会首先在它的classptah中搜索DTD文件。
                 如果你发现它是通过连接Internet查找DTD文件,就对照你的classpath目录检查XML文件里的DTD声明。
             </para>
+            
+            <sect3 id="mapping-declaration-entity-resolution">
+                <title>EntityResolver</title>
+                <para>
+                    As mentioned previously, Hibernate will first attempt to resolve DTDs in its classpath.  The
+                    manner in which it does this is by registering a custom <literal>org.xml.sax.EntityResolver</literal>
+                    implementation with the SAXReader it uses to read in the xml files.  This custom
+                    <literal>EntityResolver</literal> recognizes two different systemId namespaces.
+                    如前所述,Hibernate首先在其classpath中查找DTD。其行为是依靠在系统中注册的<literal>org.xml.sax.EntityResolver</literal>的一个具体实现,SAXReader依靠它来读取xml文件。这一 <literal>EntityResolver</literal> 实现能辨认两种不同的 systenId命名空间。
+                </para>
+                <itemizedlist>
+                    <listitem>
+                        <para>
+                            若resolver遇到了一个以<literal>http://hibernate.sourceforge.net/</literal>为开头的systemId,它会辨认出是<literal>hibernate namespace</literal>,resolver就试图通过加载Hibernate类的classloader来查找这些实体。
+                        </para>
+                    </listitem>
+                    <listitem>
+                        <para>
+
+                            若resolver遇到了一个使用<literal>classpath://</literal>URL协议的systemId,它会辨认出这是<literal>user namespace</literal>,resolver试图通过(1)当前线程上下文的classloader和(2)加载Hibernate class的classloader来查找这些实体。
+                        </para>
+                    </listitem>
+                </itemizedlist>
+                <para>
+                    使用user namespace(用户命名空间)的例子:
+                </para>
+                <programlisting><![CDATA[<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" [
+    <!ENTITY types SYSTEM "classpath://your/domain/types.xml">
+]>
+
+<hibernate-mapping package="your.domain">
+    <class name="MyEntity">
+        <id name="id" type="my-custom-id-type">
+            ...
+        </id>
+    <class>
+    &types;
+</hibernate-mapping>]]></programlisting>
+                <para>
+                    <literal>types.xml</literal>是<literal>your.domain</literal>包中的一个资源,它包含了一个定制的<xref linkend="mapping-types-custom">typedef</xref>。
+                </para>
+                
+            </sect3>
+            
         </sect2>
 
         <sect2 id="mapping-declaration-mapping" revision="3">
@@ -693,6 +740,15 @@
                             </para>
                         </listitem>
                         </varlistentry>
+                        <varlistentry>
+                        <term><literal>sequence-identity</literal></term>
+                        <listitem>
+                            <para>
+                                一种特别的序列生成策略,使用数据库序列来生成实际值,但将它和JDBC3的getGeneratedKeys结合在一起,使得在插入语句执行的时候就返回生成的值。目前为止只有面向JDK 1.4的Oracle 10g驱动支持这一策略。注意,因为Oracle驱动程序的一个bug,这些插入语句的注释被关闭了。(原文:Note comments on these insert statements are disabled due to a bug in the Oracle drivers.)
+                            </para>
+                        </listitem>
+                        </varlistentry>
+                        
                     </variablelist>
 
                 </para>
@@ -2141,7 +2197,7 @@
             <title>连接(join)</title>
 
             <para>
-               使用 <literal>&lt;join&gt;</literal> 元素,可以将一个类的属性映射到多张表中。
+               使用 <literal>&lt;join&gt;</literal> 元素,假若在表之间存在一对一关联,可以将一个类的属性映射到多张表中。
             </para>
 
             <programlistingco>

Modified: trunk/Hibernate3/doc/reference/zh-cn/modules/batch.xml
===================================================================
--- trunk/Hibernate3/doc/reference/zh-cn/modules/batch.xml	2006-11-07 01:16:53 UTC (rev 10743)
+++ trunk/Hibernate3/doc/reference/zh-cn/modules/batch.xml	2006-11-07 05:58:20 UTC (rev 10744)
@@ -26,6 +26,10 @@
     
 <programlisting><![CDATA[hibernate.jdbc.batch_size 20]]></programlisting>
 
+    <para id="disablebatching" revision="1">
+        注意,假若你使用了<literal>identiy</literal>标识符生成器,Hibernate在JDBC级别透明的关闭插入语句的批量执行。
+    </para>
+
     <para>
         你也可能想在执行批量处理时关闭二级缓存:
     </para>

Modified: trunk/Hibernate3/doc/reference/zh-cn/modules/configuration.xml
===================================================================
--- trunk/Hibernate3/doc/reference/zh-cn/modules/configuration.xml	2006-11-07 01:16:53 UTC (rev 10743)
+++ trunk/Hibernate3/doc/reference/zh-cn/modules/configuration.xml	2006-11-07 05:58:20 UTC (rev 10744)
@@ -685,9 +685,15 @@
                             为JDBC事务策略选择<literal>after_transaction</literal>.
                             <para>
                                 <emphasis role="strong">取值</emphasis>
-                                <literal>on_close</literal> | <literal>after_transaction</literal> |
-                                <literal>after_statement</literal> | <literal>auto</literal>
+                                <literal>auto</literal> (默认) | <literal>on_close</literal> |
+                                <literal>after_transaction</literal> | <literal>after_statement</literal>
                             </para>
+                            <para>
+
+                                注意,这些设置仅对通过<literal>SessionFactory.openSession</literal>得到的<literal>Session</literal>起作用。对于通过<literal>SessionFactory.getCurrentSession</literal>得到的<literal>Session</literal>,所配置的<literal>CurrentSessionContext</literal>实现控制这些<literal>Session</literal>的连接释放模式。请参阅<xref linkend="architecture-current-session"/>。
+                            </para>
+
+
   	                    </entry>
   	                </row>
   	                <row>
@@ -902,7 +908,7 @@
             </tgroup>
         </table>
 
-        <table frame="topbot" id="configuration-misc-properties" revision="9">
+        <table frame="topbot" id="configuration-misc-properties" revision="10">
             <title>
                 其他属性
             </title>
@@ -931,7 +937,7 @@
                             <para>
                                 <emphasis role="strong">eg.</emphasis>
                                 <literal>jta</literal> | <literal>thread</literal> |
-                                <literal>custom.Class</literal>
+                                <literal>managed</literal> | <literal>custom.Class</literal>
                             </para>
                         </entry>
                     </row>

Modified: trunk/Hibernate3/doc/reference/zh-cn/modules/filters.xml
===================================================================
--- trunk/Hibernate3/doc/reference/zh-cn/modules/filters.xml	2006-11-07 01:16:53 UTC (rev 10743)
+++ trunk/Hibernate3/doc/reference/zh-cn/modules/filters.xml	2006-11-07 05:58:20 UTC (rev 10744)
@@ -7,7 +7,7 @@
                 对于某个特定的Hibernate session您可以选择是否启用(或禁用)某个过滤器。
     </para>
 
-    <sect1 id="objectstate-filters">
+    <sect1 id="objectstate-filters" revision="1">
         <title>Hibernate 过滤器(filters)</title>
 
         <para>
@@ -122,7 +122,19 @@
 			最安全的方式是使用左外连接(left outer joining)。并且通常来说,先写参数,
 			然后是操作符,最后写数据库字段名。
         </para>
+        
+        <para>
+            在Filter定义之后,它可能被附加到多个实体和/或集合类,每个都有自己的条件。假若这些条件都是一样的,每次都要定义就显得很繁琐。因此,<literal>&lt;filter-def/&gt;</literal>被用来定义一个默认条件,它可能作为属性或者CDATA出现:
+        </para>
 
+        <programlisting><![CDATA[<filter-def name="myFilter" condition="abc > xyz">...</filter-def>
+<filter-def name="myOtherFilter">abc=xyz</filter-def>]]></programlisting>
+
+        <para>
+        	当这个filter被附加到任何目的地,而又没有指明条件时,这个条件就会被使用。注意,换句话说,你可以通过给filter附加特别的条件来重载默认条件。
+        </para>
+
+
     </sect1>
 
 </chapter>
\ No newline at end of file

Modified: trunk/Hibernate3/doc/reference/zh-cn/modules/performance.xml
===================================================================
--- trunk/Hibernate3/doc/reference/zh-cn/modules/performance.xml	2006-11-07 01:16:53 UTC (rev 10743)
+++ trunk/Hibernate3/doc/reference/zh-cn/modules/performance.xml	2006-11-07 05:58:20 UTC (rev 10744)
@@ -564,10 +564,8 @@
 			(即使可以将缓存数据设定为定期失效)。 
         </para>
         
-        <para>
-			默认情况下,Hibernate使用EHCache进行JVM级别的缓存(目前,Hibernate已经废弃了对JCS的支持,未来版本中将会去掉它)。
-			你可以通过设置<literal>hibernate.cache.provider_class</literal>属性,指定其他的缓存策略,
-			该缓存策略必须实现<literal>org.hibernate.cache.CacheProvider</literal>接口。
+        <para revision="1">
+            通过在<literal>hibernate.cache.provider_class</literal>属性中指定<literal>org.hibernate.cache.CacheProvider</literal>的某个实现的类名,你可以选择让Hibernate使用哪个缓存实现。Hibernate打包一些开源缓存实现,提供对它们的内置支持(见下表)。除此之外,你也可以实现你自己的实现,将它们插入到系统中。注意,在3.2版本之前,默认使用EhCache 作为缓存实现,但从3.2起就不再这样了。
 		</para>
 
         <table frame="topbot" id="cacheproviders" revision="1">

Modified: trunk/Hibernate3/doc/reference/zh-cn/modules/persistent_classes.xml
===================================================================
--- trunk/Hibernate3/doc/reference/zh-cn/modules/persistent_classes.xml	2006-11-07 01:16:53 UTC (rev 10743)
+++ trunk/Hibernate3/doc/reference/zh-cn/modules/persistent_classes.xml	2006-11-07 05:58:20 UTC (rev 10744)
@@ -435,11 +435,11 @@
 				</para>
     </sect1>
 
-    <sect1 id="persistent-classes-tuplizers" revision="0">
+    <sect1 id="persistent-classes-tuplizers" revision="1">
         <title>元组片断映射(Tuplizers)</title>
 
         <para>
-            <literal>org.hibernate.tuple.Tuplizer</literal>,以及其子接口,负责根据给定的<literal>org.hibernate.EntityMode</literal>,来复现片断数据。如果给定的片断数据被认为其是一种数据结构,"tuplizer"就是一个知道如何创建这样的数据结构,以及如何给这个数据结构赋值的东西。比如说,对于POJO这种Entity Mode,对应的tuplizer知道通过其构造方法来创建一个POJO,再通过其属性访问器来访问POJO属性。有两大类高层Tuplizer,分别是<literal>org.hibernate.tuple.EntityTuplizer</literal> 和<literal>org.hibernate.tuple.ComponentTuplizer</literal>接口。<literal>EntityTuplizer</literal>负责管理上面提到的实体的契约,而<literal>ComponentTuplizer</literal>则是针对组件的。
+            <literal>org.hibernate.tuple.Tuplizer</literal>,以及其子接口,负责根据给定的<literal>org.hibernate.EntityMode</literal>,来复现片断数据。如果给定的片断数据被认为其是一种数据结构,"tuplizer"就是一个知道如何创建这样的数据结构,以及如何给这个数据结构赋值的东西。比如说,对于POJO这种Entity Mode,对应的tuplizer知道通过其构造方法来创建一个POJO,再通过其属性访问器来访问POJO属性。有两大类高层Tuplizer,分别是<literal>org.hibernate.tuple.entity.EntityTuplizer</literal> 和<literal>org.hibernate.tuple.entity.ComponentTuplizer</literal>接口。<literal>EntityTuplizer</literal>负责管理上面提到的实体的契约,而<literal>ComponentTuplizer</literal>则是针对组件的。
         </para>
 
         <para>
@@ -466,7 +466,7 @@
 
 
 public class CustomMapTuplizerImpl
-        extends org.hibernate.tuple.DynamicMapEntityTuplizer {
+        extends org.hibernate.tuple.entity.DynamicMapEntityTuplizer {
     // override the buildInstantiator() method to plug in our custom map...
     protected final Instantiator buildInstantiator(
             org.hibernate.mapping.PersistentClass mappingInfo) {

Modified: trunk/Hibernate3/doc/reference/zh-cn/modules/query_hql.xml
===================================================================
--- trunk/Hibernate3/doc/reference/zh-cn/modules/query_hql.xml	2006-11-07 01:16:53 UTC (rev 10743)
+++ trunk/Hibernate3/doc/reference/zh-cn/modules/query_hql.xml	2006-11-07 05:58:20 UTC (rev 10744)
@@ -772,7 +772,7 @@
         </para>
     </sect1>
 
-    <sect1 id="queryhql-grouping">
+    <sect1 id="queryhql-grouping" revision="1">
         <title>group by子句</title>
 
         <para>
@@ -804,13 +804,15 @@
         <programlisting><![CDATA[select cat
 from Cat cat
     join cat.kittens kitten
-group by cat
+group by cat.id, cat.name, cat.other, cat.properties
 having avg(kitten.weight) > 100
 order by count(kitten) asc, sum(kitten.weight) desc]]></programlisting>
 
         <para>
             注意<literal>group by</literal>子句与
             <literal>order by</literal>子句中都不能包含算术表达式(arithmetic expressions).
+            
+			也要注意Hibernate目前不会扩展group的实体,因此你不能写<literal>group by cat</literal>,除非<literal>cat</literal>的所有属性都不是聚集的(non-aggregated)。你必须明确的列出所有的非聚集属性。
         </para>
 
     </sect1>

Modified: trunk/Hibernate3/doc/reference/zh-cn/modules/query_sql.xml
===================================================================
--- trunk/Hibernate3/doc/reference/zh-cn/modules/query_sql.xml	2006-11-07 01:16:53 UTC (rev 10743)
+++ trunk/Hibernate3/doc/reference/zh-cn/modules/query_sql.xml	2006-11-07 05:58:20 UTC (rev 10744)
@@ -10,15 +10,36 @@
 		Hibernate3允许你使用手写的sql来完成所有的create,update,delete,和load操作(包括存储过程)
     </para>
 
-    <sect1 id="querysql-creating" revision="3">
+    <sect1 id="querysql-creating" revision="4">
     <title>使用<literal>SQLQuery</literal></title>
 
-    <para>对原生SQL查询执行的控制是通过<literal>SQLQuery</literal>接口进行的,通过执行<literal>Session.createSQLQuery()</literal>获取这个接口。最简单的情况下,我们可以采用以下形式:</para>
+    <para>对原生SQL查询执行的控制是通过<literal>SQLQuery</literal>接口进行的,通过执行<literal>Session.createSQLQuery()</literal>获取这个接口。下面来描述如何使用这个API进行查询。</para>
 
-    <programlisting><![CDATA[List cats = sess.createSQLQuery("select * from cats")
-    .addEntity(Cat.class)
-    .list();]]></programlisting>
+    <sect2>
+      <title>标量查询(Scalar queries)</title>
 
+      <para>
+      最基本的SQL查询就是获得一个标量(数值)的列表。      </para>
+
+      <programlisting><![CDATA[sess.createSQLQuery("SELECT * FROM CATS").list();
+sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").list();
+]]></programlisting>
+
+      <para>
+      它们都将返回一个Object数组(Object[])组成的List,数组每个元素都是CATS表的一个字段值。Hibernate会使用ResultSetMetadata来判定返回的标量值的实际顺序和类型。
+      </para>
+
+      <para>
+      如果要避免过多的使用<literal>ResultSetMetadata</literal>,或者只是为了更加明确的指名返回值,可以使用<literal>addScalar()</literal>。
+      </para>
+
+      <programlisting><![CDATA[sess.createSQLQuery("SELECT * FROM CATS")
+ .addScalar("ID", Hibernate.LONG)
+ .addScalar("NAME", Hibernate.STRING)
+ .addScalar("BIRTHDATE", Hibernate.DATE)
+]]></programlisting>
+
+
     <para>这个查询指定了:</para>
 
     <itemizedlist>
@@ -27,89 +48,164 @@
       </listitem>
 
       <listitem>
-        <para>查询返回的实体</para>
+        <para>要返回的字段和类型</para>
       </listitem>
     </itemizedlist>
 
-    <para>这里,结果集字段名被假设为与映射文件中指明的字段名相同。对于连接了多个表的查询,这就可能造成问题,因为可能在多个表中出现同样名字的字段。下面的方法就可以避免字段名重复的问题:</para>
+      <para>
+      它仍然会返回Object数组,但是此时不再使用<literal>ResultSetMetdata</literal>,而是明确的将ID,NAME和BIRTHDATE按照Long,String和Short类型从resultset中取出。同时,也指明了就算query是使用<literal>*</literal>来查询的,可能获得超过列出的这三个字段,也仅仅会返回这三个字段。
+      </para>
 
-    <programlisting><![CDATA[List cats = sess.createSQLQuery("select {cat.*} from cats cat")
-    .addEntity("cat", Cat.class)
-    .list();]]></programlisting>
+      <para>
+      对全部或者部分的标量值不设置类型信息也是可以的。
+      </para>
 
-        <para>
-			这个查询指定了:
-        </para>
+      <programlisting><![CDATA[sess.createSQLQuery("SELECT * FROM CATS")
+ .addScalar("ID", Hibernate.LONG)
+ .addScalar("NAME")
+ .addScalar("BIRTHDATE")
+]]></programlisting>
 
-        <itemizedlist>
+      <para>
+      基本上这和前面一个查询相同,只是此时使用<literal>ResultSetMetaData</literal>来决定NAME和BIRTHDATE的类型,而ID的类型是明确指出的。
+      </para>
+
+      <para>
+      关于从ResultSetMetaData返回的java.sql.Types是如何映射到Hibernate类型,是由方言(Dialect)控制的。假若某个指定的类型没有被映射,或者不是你所预期的类型,你可以通过Dialet的<literal>registerHibernateType</literal>调用自行定义。
+      </para>
+
+    </sect2>
+
+    <sect2>
+      <title>实体查询(Entity queries)</title>
+
+      <para>
+      上面的查询都是返回标量值的,也就是从resultset中返回的“裸”数据。下面展示如何通过<literal>addEntity()</literal>让原生查询返回实体对象。
+      </para>
+
+      <programlisting><![CDATA[sess.createSQLQuery("SELECT * FROM CATS").addEntity(Cat.class);
+sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").addEntity(Cat.class);
+]]></programlisting>
+
+      <para>这个查询指定:</para>
+
+      <itemizedlist>
         <listitem>
-        <para>
-			SQL查询语句,它带一个占位符,可以让Hibernate使用字段的别名.
-        </para>
+          <para>SQL查询字符串</para>
         </listitem>
+
         <listitem>
-        <para>
-			查询返回的实体,和它的SQL表的别名.
-        </para>
+          <para>要返回的实体</para>
         </listitem>
-        </itemizedlist>
-    
-        <para>
-			<literal>addEntity()</literal>方法将SQL表的别名和实体类联系起来,并且确定查询结果集的形态。
-        </para>
-        
-        <para>
-			<literal>addJoin()</literal>方法可以被用于载入其他的实体和集合的关联.
-        </para>
-    
-    <programlisting><![CDATA[List cats = sess.createSQLQuery(
-        "select {cat.*}, {kitten.*} from cats cat, cats kitten where kitten.mother = cat.id"
-    )
-    .addEntity("cat", Cat.class)
-    .addJoin("kitten", "cat.kittens")
-    .list();]]></programlisting>
-            
-        <para>
-			原生的SQL查询可能返回一个简单的标量值或者一个标量和实体的结合体。
-        </para>
+      </itemizedlist>
 
-        <programlisting><![CDATA[Double max = (Double) sess.createSQLQuery("select max(cat.weight) as maxWeight from cats cat")
-        .addScalar("maxWeight", Hibernate.DOUBLE);
-        .uniqueResult();]]></programlisting>
-        
-    <para>除此之外,你还可以在你的hbm文件中描述结果集映射信息,在查询中使用。</para>
-    
-    <programlisting><![CDATA[List cats = sess.createSQLQuery(
-        "select {cat.*}, {kitten.*} from cats cat, cats kitten where kitten.mother = cat.id"
-    )
-    .setResultSetMapping("catAndKitten")
-    .list();]]></programlisting>
+      <para>
+      假设Cat被映射为拥有ID,NAME和BIRTHDATE三个字段的类,以上的两个查询都返回一个List,每个元素都是一个Cat实体。
+      </para>
 
+      <para>      
+      假若实体在映射时有一个<literal>many-to-one</literal>的关联指向另外一个实体,在查询时必须也返回那个实体,否则会导致发生一个"column not found"的数据库错误。这些附加的字段可以使用*标注来自动返回,但我们希望还是明确指明,看下面这个具有指向<literal>Dog</literal>的<literal>many-to-one</literal>的例子:
+      </para>
 
-    </sect1>
+      <programlisting><![CDATA[sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE, DOG_ID FROM CATS").addEntity(Cat.class);
+]]></programlisting>
 
-    <sect1 id="querysql-aliasreferences">
-        <title>别名和属性引用</title>
+      <para>
+      这样cat.getDog()就能正常运作。
+      </para>
+    </sect2>
 
-        <para>
-			上面使用的<literal>{cat.*}</literal>标记是 "所有属性" 的简写.你可以显式地列出需要的字段,但是你必须让Hibernate
-			为每一个属性注入字段的别名.这些字段的站位符是以字段别名为前导,再加上属性名.在下面的例子里,我们从一个其他的表(<literal>cat_log</literal>)
-			中获取<literal>Cat</literal>对象,而非Cat对象原本在映射元数据中声明的表.注意我们甚至在where子句中也可以使用属性别名.
-            对于命名查询,{}语法并不是必需的.你可以在<xref linkend="querysql-namedqueries"/>得到更多的细节.
-        </para>
+    <sect2>
+      <title>处理关联和集合类(Handling associations and collections)</title>
 
-        <programlisting><![CDATA[String sql = "select cat.originalId as {cat.id}, " +
-    "cat.mateid as {cat.mate}, cat.sex as {cat.sex}, " +
-    "cat.weight*10 as {cat.weight}, cat.name as {cat.name} " +
-    "from cat_log cat where {cat.mate} = :catId"
-    
+      <para>      
+      通过提前抓取将<literal>Dog</literal>连接获得,而避免初始化proxy带来的额外开销也是可能的。这是通过<literal>addJoin()</literal>方法进行的,这个方法可以让你将关联或集合连接进来。
+      </para>
+
+      <programlisting><![CDATA[sess.createSQLQuery("SELECT c.ID, NAME, BIRTHDATE, DOG_ID, D_ID, D_NAME FROM CATS c, DOGS d WHERE c.DOG_ID = d.D_ID")
+ .addEntity("cat", Cat.class)
+ .addJoin("cat.dog");
+]]></programlisting>
+
+      <para>
+            上面这个例子中,返回的<literal>Cat</literal>对象,其<literal>dog</literal>属性被完全初始化了,不再需要数据库的额外操作。注意,我们加了一个别名("cat"),以便指明join的目标属性路径。通过同样的提前连接也可以作用于集合类,例如,假若<literal>Cat</literal>有一个指向<literal>Dog</literal>的一对多关联。
+      </para>
+
+      <programlisting><![CDATA[sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE, D_ID, D_NAME, CAT_ID FROM CATS c, DOGS d WHERE c.ID = d.CAT_ID")
+ .addEntity("cat", Cat.class)
+ .addJoin("cat.dogs");
+]]></programlisting>
+
+      <p>
+      到此为止,我们碰到了天花板:若不对SQL查询进行增强,这些已经是在Hibernate中使用原生SQL查询所能做到的最大可能了。下面的问题即将出现:返回多个同样类型的实体怎么办?或者默认的别名/字段不够又怎么办?
+      
+      </p>
+    </sect2>
+
+    <sect2>
+      <title>返回多个实体(Returning multiple entities)</title>
+
+      <para>
+      到目前为止,结果集字段名被假定为和映射文件中指定的的字段名是一致的。假若SQL查询连接了多个表,同一个字段名可能在多个表中出现多次,这就会造成问题。
+      </para>
+
+      <para>
+      下面的查询中需要使用字段别名注射(这个例子本身会失败):
+      </para>
+
+      <programlisting><![CDATA[sess.createSQLQuery("SELECT c.*, m.*  FROM CATS c, CATS m WHERE c.MOTHER_ID = c.ID")
+ .addEntity("cat", Cat.class)
+ .addEntity("mother", Cat.class)
+]]></programlisting>
+
+      <para>
+      这个查询的本意是希望每行返回两个Cat实例,一个是cat,另一个是它的妈妈。但是因为它们的字段名被映射为相同的,而且在某些数据库中,返回的字段别名是“c.ID”,"c.NAME"这样的形式,而它们和在映射文件中的名字("ID"和"NAME")不匹配,这就会造成失败。
+      
+      </para>
+
+      <para>
+      下面的形式可以解决字段名重复:
+      </para>
+
+      <programlisting><![CDATA[sess.createSQLQuery("SELECT {cat.*}, {mother.*}  FROM CATS c, CATS m WHERE c.MOTHER_ID = c.ID")
+ .addEntity("cat", Cat.class)
+ .addEntity("mother", Cat.class)
+]]></programlisting>
+
+      <para>这个查询指明:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>
+          SQL查询语句,其中包含占位附来让Hibernate注射字段别名</para>
+        </listitem>
+
+        <listitem>
+          <para>
+          查询返回的实体
+          </para>
+        </listitem>
+      </itemizedlist>
+
+      <para>
+      上面使用的{cat.*}和{mother.*}标记是作为“所有属性”的简写形式出现的。当然你也可以明确地罗列出字段名,但在这个例子里面我们让Hibernate来为每个属性注射SQL字段别名。字段别名的占位符是属性名加上表别名的前缀。在下面的例子中,我们从另外一个表(cat_log)中通过映射元数据中的指定获取Cat和它的妈妈。注意,要是我们愿意,我们甚至可以在where子句中使用属性别名。
+      
+      </para>
+
+      <programlisting><![CDATA[String sql = "SELECT ID as {c.id}, NAME as {c.name}, " + 
+         "BIRTHDATE as {c.birthDate}, MOTHER_ID as {c.mother}, {mother.*} " +
+         "FROM CAT_LOG c, CAT_LOG m WHERE {c.mother} = c.ID";
+
 List loggedCats = sess.createSQLQuery(sql)
-    .addEntity("cat", Cat.class)
-    .setLong("catId", catId)
-    .list();]]></programlisting>
+        .addEntity("cat", Cat.class)
+        .addEntity("mother", Cat.class).list()
+]]></programlisting>
 
+      <sect3 id="querysql-aliasreferences" revision="2">
+        <title>别名和属性引用(Alias and property references)</title>
+
         <para>
-            <emphasis>注意:</emphasis>如果你明确地列出了每个属性,你必须包含<emphasis>这个类</emphasis>和<emphasis>它的子类</emphasis>的属性!
+        大多数情况下,都需要上面的属性注射,但在使用更加复杂的映射,比如复合属性、通过标识符构造继承树,以及集合类等等情况下,也有一些特别的别名,来允许Hibernate注射合适的别名。
         </para>
 
     <para>
@@ -119,7 +215,7 @@
     <table frame="topbot" id="aliasinjection-summary">
       <title>别名注射(alias injection names)</title>
 
-      <tgroup cols="4">
+      <tgroup cols="3">
         <colspec colwidth="1*" />
 
         <colspec colwidth="1*" />
@@ -129,7 +225,9 @@
         <thead>
           <row>
             <entry>描述</entry>
+            
             <entry>语法</entry>
+            
             <entry>示例</entry>
             </row>
         </thead>
@@ -190,8 +288,64 @@
     </table>
 
 
-    </sect1>
+    </sect3>
+   </sect2>
+   
+       <sect2>
+      <title>返回非受管实体(Returning non-managed entities)</title>
+
+      <para>
+      可以对原生sql 查询使用ResultTransformer。这会返回不受Hibernate管理的实体。
+      
+      </para>
+
+      <programlisting><![CDATA[sess.createSQLQuery("SELECT NAME, BIRTHDATE FROM CATS")
+        .setResultTransformer(Transformers.aliasToBean(CatDTO.class))]]></programlisting>
+        
+              <para>这个查询指定:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>SQL查询字符串</para>
+        </listitem>
+
+        <listitem>
+          <para>结果转换器(result transformer)</para>
+        </listitem>
+      </itemizedlist>
+        
+        <para>
+        上面的查询将会返回<literal>CatDTO</literal>的列表,它将被实例化并且将NAME和BIRTHDAY的值注射入对应的属性或者字段。
+        </para>
+    </sect2>
+
+    <sect2>
+      <title>处理继承(Handling inheritance)</title>
+
+      <para>
+      原生SQL查询假若其查询结果实体是继承树中的一部分,它必须包含基类和所有子类的所有属性。
+      </para>
+    </sect2>
+
+    <sect2>
+      <title>参数(Parameters)</title>
+
+      <para>
+      原生查询支持位置参数和命名参数:
+      </para>
+
+      <programlisting><![CDATA[Query query = sess.createSQLQuery("SELECT * FROM CATS WHERE NAME like ?").addEntity(Cat.class);
+List pusList = query.setString(0, "Pus%").list();
+     
+query = sess.createSQLQuery("SELECT * FROM CATS WHERE NAME like :name").addEntity(Cat.class);
+List pusList = query.setString("name", "Pus%").list();          ]]></programlisting>
+    </sect2>
     
+    
+        
+  </sect1>
+
+    
     <sect1 id="querysql-namedqueries" revision="3">
         <title>命名SQL查询</title>
 
@@ -272,6 +426,16 @@
         ON person.ID = address.PERSON_ID AND address.TYPE='MAILING'
     WHERE person.NAME LIKE :namePattern
 </sql-query>]]></programlisting>
+
+	    <para>
+    	另外,你可以在java代码中直接使用hbm文件中的结果集定义信息。
+    </para>
+
+    <programlisting><![CDATA[List cats = sess.createSQLQuery(
+        "select {cat.*}, {kitten.*} from cats cat, cats kitten where kitten.mother = cat.id"
+    )
+    .setResultSetMapping("catAndKitten")
+    .list();]]></programlisting>
          
          <sect2 id="propertyresults">
              <title>使用return-property来明确地指定字段/别名</title>

Modified: trunk/Hibernate3/doc/reference/zh-cn/modules/session_api.xml
===================================================================
--- trunk/Hibernate3/doc/reference/zh-cn/modules/session_api.xml	2006-11-07 01:16:53 UTC (rev 10743)
+++ trunk/Hibernate3/doc/reference/zh-cn/modules/session_api.xml	2006-11-07 05:58:20 UTC (rev 10744)
@@ -408,7 +408,7 @@
 
             </sect3>
 
-            <sect3 id="objectstate-querying-executing-named">
+            <sect3 id="objectstate-querying-executing-named" revision="1">
                 <title>外置命名查询(Externalizing named queries)</title>
 
                 <para>
@@ -416,7 +416,7 @@
 					(如果你的查询串中包含可能被解释为XML标记(markup)的字符,别忘了用<literal>CDATA</literal>包裹起来。)
                 </para>                
 
-                <programlisting><![CDATA[<query name="eg.DomesticCat.by.name.and.minimum.weight"><![CDATA[
+                <programlisting><![CDATA[<query name="ByNameAndMaximumWeight"><![CDATA[
     from eg.DomesticCat as cat
         where cat.name = ?
         and cat.weight > ?
@@ -427,7 +427,7 @@
 					参数绑定及执行以编程方式(programatically)完成:
                 </para>                
 
-                <programlisting><![CDATA[Query q = sess.getNamedQuery("eg.DomesticCat.by.name.and.minimum.weight");
+                <programlisting><![CDATA[Query q = sess.getNamedQuery("ByNameAndMaximumWeight");
 q.setString(0, name);
 q.setInt(1, minWeight);
 List cats = q.list();]]></programlisting>
@@ -438,6 +438,11 @@
                 	或将原有的其他的查询语句放在配置文件中,这样就可以让Hibernate统一管理,达到迁移的目的。
                 </para>                
 
+                <para>
+
+                     也请注意在<literal>&lt;hibernate-mapping&gt;</literal>元素中声明的查询必须有一个全局唯一的名字,而在<literal>&lt;class&gt;</literal>元素中声明的查询自动具有全局名,是通过类的全名加以限定的。比如<literal>eg.Cat.ByNameAndMaximumWeight</literal>。
+                </para>
+
             </sect3>
 
         </sect2>

Modified: trunk/Hibernate3/doc/reference/zh-cn/modules/tutorial.xml
===================================================================
--- trunk/Hibernate3/doc/reference/zh-cn/modules/tutorial.xml	2006-11-07 01:16:53 UTC (rev 10743)
+++ trunk/Hibernate3/doc/reference/zh-cn/modules/tutorial.xml	2006-11-07 05:58:20 UTC (rev 10744)
@@ -258,7 +258,7 @@
             </para>
 
             <para>
-	在开发的根目录下创建一个<literal>data</literal>目录 - 这是HSQL DB存储数据文件的地方。此时在data目录中运行<literal>java -classpath lib/hsqldb.jar org.hsqldb.Server</literal>就可启动数据库。你可以在log中看到它的启动,及绑定到TCP/IP套结字,这正是我们的应用程序稍后会连接的地方。如果你希望在本例中运行一个全新的数据库,就在窗口中按下<literal>CTRL + C</literal>来关闭HSQL数据库,并删除<literal>data/</literal>目录下的所有文件,再重新启动HSQL数据库。
+	在开发的根目录下创建一个<literal>data</literal>目录 - 这是HSQL DB存储数据文件的地方。此时在data目录中运行<literal>java -classpath ../lib/hsqldb.jar org.hsqldb.Server</literal>就可启动数据库。你可以在log中看到它的启动,及绑定到TCP/IP套结字,这正是我们的应用程序稍后会连接的地方。如果你希望在本例中运行一个全新的数据库,就在窗口中按下<literal>CTRL + C</literal>来关闭HSQL数据库,并删除<literal>data/</literal>目录下的所有文件,再重新启动HSQL数据库。
             </para>
 
             <para>
@@ -462,7 +462,7 @@
 
         </sect2>
 
-        <sect2 id="tutorial-firstapp-workingpersistence"  revision="4">
+        <sect2 id="tutorial-firstapp-workingpersistence"  revision="5">
             <title>
 	加载并存储对象
 		</title>
@@ -518,10 +518,22 @@
             </para>
 
             <para>
-                <literal>sessionFactory.getCurrentSession()</literal>是干什么的呢?首先,只要你持有<literal>SessionFactory</literal>(幸亏我们有<literal>HibernateUtil</literal>,可以随时获得),大可在任何时候、任何地点调用这个方法。<literal>getCurrentSession()</literal>方法总会返回“当前的”工作单元。记得我们在<literal>hibernate.cfg.xml</literal>中把这一配置选项调整为"thread"了吗?因此,当前工作单元的范围就是当前执行我们应用程序的Java线程。但是,这并非总是正确的。 <literal>Session</literal>在第一次被使用的时候,或者第一次调用<literal>getCurrentSession()</literal>的时候,其生命周期就开始。然后它被Hibernate绑定到当前线程。当事务结束的时候,不管是提交还是回滚,Hibernate也会把<literal>Session</literal>从当前线程剥离,并且关闭它。假若你再次调用<literal>getCurrentSession()</lit!
 eral>,你会得到一个新的<literal>Session</literal>,并且开始一个新的工作单元。这种<emphasis>线程绑定(thread-bound)</emphasis>的编程模型(model)是使用Hibernate的最广泛的方式。
+                <literal>sessionFactory.getCurrentSession()</literal>是干什么的呢?首先,只要你持有<literal>SessionFactory</literal>(幸亏我们有<literal>HibernateUtil</literal>,可以随时获得),大可在任何时候、任何地点调用这个方法。<literal>getCurrentSession()</literal>方法总会返回“当前的”工作单元。记得我们在<literal>hibernate.cfg.xml</literal>中把这一配置选项调整为"thread"了吗?因此,因此,当前工作单元被绑定到当前执行我们应用程序的Java线程。但是,这并非是完全准确的,你还得考虑工作单元的生命周期范围 (scope),它何时开始,又何时结束. 
+             </para>
+
+             <para>
+                <literal>Session</literal>在第一次被使用的时候,即第一次调用<literal>getCurrentSession()</literal>的时候,其生命周期就开始。然后它被Hibernate绑定到当前线程。当事务结束的时候,不管是提交还是回滚,Hibernate会自动把<literal>Session</literal>从当前线程剥离,并且关闭它。假若你再次调用<literal>getCurrentSession()</literal>,你会得到一个新的<literal>Session</literal>,并且开始一个新的工作单元。这种<emphasis>线程绑定(thread-bound)</emphasis>的编程模型(model)是使用Hibernate的最广泛的方式,因为它支持对你的代码灵活分层(事务划分可以和你的数据访问代码分离开来,在本教程的后面部分就会这么做)。
+  
             </para>
 
             <para>
+                
+                和工作单元的生命周期这个话题相关,Hibernate <literal>Session</literal>是否被应该用来执行多次数据库操作?上面的例子对每一次操作使用了一个<literal>Session</literal>,这完全是巧合,这个例子不是很复杂,无法展示其他方式。Hibernate <literal>Session</literal>的生命周期可以很灵活,但是你绝不要把你的应用程序设计成为<emphasis>每一次</emphasis>数据库操作都用一个新的Hibernate <literal>Session</literal>。因此就算下面的例子(它们都很简单)中你可以看到这种用法,记住<emphasis>每次操作一个session</emphasis>是一个反模式。在本教程的后面会展示一个真正的(web)程序。
+            </para>
+
+            
+
+            <para>
                 关于事务处理及事务边界界定的详细信息,请参看<xref linkend="transactions"/>。在上面的例子中,我们也忽略了所有的错误与回滚的处理。
             </para>
 
@@ -750,7 +762,7 @@
 
         </sect2>
 
-        <sect2 id="tutorial-associations-working"  revision="1">
+        <sect2 id="tutorial-associations-working"  revision="2">
             <title>
 	使关联工作
 	</title>
@@ -820,7 +832,8 @@
     Long eventId = mgr.createAndStoreEvent("My Event", new Date());
     Long personId = mgr.createAndStorePerson("Foo", "Bar");
     mgr.addPersonToEvent(personId, eventId);
-    System.out.println("Added person " + personId + " to event " + eventId);]]></programlisting>
+    System.out.println("Added person " + personId + " to event " + eventId);
+}]]></programlisting>
 
             <para>
 	上面是个关于两个同等重要的实体类间关联的例子。像前面所提到的那样,在特定的模型中也存在其它的类和类型,这些类和类型通常是“次要的”。你已看到过其中的一些,像<literal>int</literal>或<literal>String</literal>。我们称这些类为<emphasis>值类型(value type)</emphasis>,它们的实例<emphasis>依赖(depend)</emphasis>在某个特定的实体上。这些类型的实例没有它们自己的标识(identity),也不能在实体间被共享(比如,两个person不能引用同一个<literal>firstname</literal>对象,即使他们有相同的first name)。当然,值类型并不仅仅在JDK中存在(事实上,在一个Hibernate应用程序中,所有的JDK类都被视为值类型),而且你也可以编写你自己的依赖类,例如<literal>Address</literal>,<literal>MonetaryAmount</literal>。
@@ -1001,7 +1014,7 @@
             Hibernate web应用程序使用<literal>Session</literal> 和<literal>Transaction</literal>的方式几乎和独立应用程序是一样的。但是,有一些常见的模式(pattern)非常有用。现在我们编写一个<literal>EventManagerServlet</literal>。这个servlet可以列出数据库中保存的所有的events,还提供一个HTML表单来增加新的events。
         </para>
 
-        <sect2 id="tutorial-webapp-servlet">
+        <sect2 id="tutorial-webapp-servlet" revision="2">
             <title>编写基本的servlet</title>
 
             <para>
@@ -1014,9 +1027,6 @@
 
 public class EventManagerServlet extends HttpServlet {
 
-    private final SimpleDateFormat dateFormatter =
-                            new SimpleDateFormat("dd.MM.yyyy");
-
     // Servlet code
 }]]></programlisting>
 
@@ -1032,6 +1042,8 @@
                      HttpServletResponse response)
         throws ServletException, IOException {
 
+    SimpleDateFormat dateFormatter = new SimpleDateFormat("dd.MM.yyyy");
+
     try {
         // Begin unit of work
         HibernateUtil.getSessionFactory()
@@ -1050,11 +1062,15 @@
     }
 
 }]]></programlisting>
-
             <para>
 我们称这里应用的模式为每次请求一个session<emphasis>(session-per-request)</emphasis>。当有请求到达这个servlet的时候,通过对<literal>SessionFactory</literal>的第一次调用,打开一个新的Hibernate <literal>Session</literal>。然后启动一个数据库事务&mdash;所有的数据访问都是在事务中进行,不管是读还是写(我们在应用程序中不使用auto-commit模式)。
             </para>
+            
+            <para>
 
+                <emphasis>不要</emphasis>为每次数据库操作都使用一个新的Hibernate <literal>Session</literal>。将Hibernate <literal>Session</literal>的范围设置为整个请求。要用<literal>getCurrentSession()</literal>,这样它自动会绑定到当前Java线程。
+            </para>
+
             <para>
                 下一步,对请求的可能动作进行处理,渲染出反馈的HTML。我们很快就会涉及到那部分。
             </para>
@@ -1065,7 +1081,7 @@
 
         </sect2>
 
-        <sect2 id="tutorial-webapp-processing">
+        <sect2 id="tutorial-webapp-processing" revision="1">
             <title>处理与渲染</title>
 
             <para>
@@ -1092,31 +1108,18 @@
 
 // Print page
 printEventForm(out);
-listEvents(out);
+listEvents(out, dateFormatter);
 
 // Write HTML footer
 out.println("</body></html>");
 out.flush();
 out.close();]]></programlisting>
-
             <para>
-                必须承认,这种编码风格让Java与HTML混合在了一起,在更复杂的应用程序中不应大量地使用&mdash;记住我们在章中仅为了展示Hibernate的基本概念。这段代码打印出了HTML头和尾部。在页面中,打印出一个输入event条目的表单,并列出数据库中所有events。第一个方法微不足道,仅仅是输出HTML:
+                <literal>listEvents()</literal>方法使用绑定到当前线程的Hibernate <literal>Session</literal>来执行查询:
             </para>
 
-            <programlisting><![CDATA[private void printEventForm(PrintWriter out) {
-    out.println("<h2>Add new event:</h2>");
-    out.println("<form>");
-    out.println("Title: <input name='eventTitle' length='50'/><br/>");
-    out.println("Date (e.g. 24.12.2009): <input name='eventDate' length='10'/><br/>");
-    out.println("<input type='submit' name='action' value='store'/>");
-    out.println("</form>");
-}]]></programlisting>
+            <programlisting><![CDATA[private void listEvents(PrintWriter out, SimpleDateFormat dateFormatter) {
 
-            <para>
-                <literal>listEvents()</literal>方法使用绑定到当前线程的Hibernate <literal>Session</literal>来执行查询:
-            </para>
-
-            <programlisting><![CDATA[private void listEvents(PrintWriter out) {
     List result = HibernateUtil.getSessionFactory()
                     .getCurrentSession().createCriteria(Event.class).list();
     if (result.size() > 0) {




More information about the hibernate-commits mailing list