reviewed chapters

git-svn-id: https://svn.jboss.org/repos/hibernate/trunk/Hibernate3/doc@9197 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Xiaogang Cao 2006-02-02 09:08:49 +00:00
parent 53a910b83d
commit 9b5c1fc8c5
6 changed files with 236 additions and 247 deletions

View File

@ -1,18 +1,18 @@
<chapter id="components"> <chapter id="components">
<title>组件Component映射</title> <title>组件Component映射</title>
<para>
<emphasis>组件</emphasis>(Component)这个概念在Hibernate中几处不同的地方为了不同的目的被重复使用.
</para>
<sect1 id="components-dependentobjects" revision="2">
<title>依赖对象Dependent objects</title>
<para> <para>
<emphasis>Component</emphasis>这个概念在Hibernate中几处不同的地方为了不同的目的被重复使用. 组件(Component)是一个被包含的对象,在持久化的过程中,它被当作值类型,而并非一个实体的引用。在这篇文档中,组件这一术语指的是面向对象的合成概念(而并不是系统构架层次上的组件的概念)。举个例子, 你对人(Person)这个概念可以像下面这样来建模:
</para> </para>
<sect1 id="components-dependentobjects" revision="2" > <programlisting><![CDATA[public class Person {
<title>依赖对象Dependent objects</title>
<para>
Component是一个被包含的对象,它作为值类型被持久化而非一个被引用的实体。“component(组件)”这一术语指的是面向对象的合成概念(而并不是系统构架层次上的组件的概念)举个例子, 你可以对人Person)如以下这样来建模:
</para>
<programlisting><![CDATA[public class Person {
private java.util.Date birthday; private java.util.Date birthday;
private Name name; private Name name;
private String key; private String key;
@ -38,7 +38,7 @@
...... ......
}]]></programlisting> }]]></programlisting>
<programlisting><![CDATA[public class Name { <programlisting><![CDATA[public class Name {
char initial; char initial;
String first; String first;
String last; String last;
@ -63,12 +63,11 @@
}]]></programlisting> }]]></programlisting>
<para> <para>
现在,<literal>姓名(Name)</literal>是作为<literal>人(Person)</literal>的一个组成部分。需要注意的是:需要对<literal>姓名</literal> 在持久化的过程中,<literal>姓名(Name)</literal>可以作为<literal>人(Person)</literal>的一个组件。需要注意的是:你应该为<literal>姓名</literal>的持久化属性定义getter和setter方法,但是你不需要实现任何的接口或申明标识符字段。
的持久化属性定义getter和setter方法,但是不需要实现任何的接口或申明标识符字段。
</para> </para>
<para> <para>
以下是这个例子的Hibernate映射文件: 以下是这个例子的Hibernate映射文件:
</para> </para>
<programlisting><![CDATA[<class name="eg.Person" table="person"> <programlisting><![CDATA[<class name="eg.Person" table="person">
@ -83,80 +82,82 @@
</component> </component>
</class>]]></programlisting> </class>]]></programlisting>
<para> <para>
人员(Person)表中将包括<literal>pid</literal>, 人员(Person)表中将包括<literal>pid</literal>,
<literal>birthday</literal>, <literal>birthday</literal>,
<literal>initial</literal>, <literal>initial</literal>,
<literal>first</literal> <literal>first</literal>
<literal>last</literal>等字段。 <literal>last</literal>等字段。</para>
</para>
<para> <para>
就像所有的值类型一样, Component不支持共享引用。 就像所有的值类型一样, 组件不支持共享引用。
换句话说,两个人可能重名,但是两个person对象应该包含两个独立的name对象只不过是具有“同样”的值。 换句话说,两个人可能重名,但是两个Person对象应该包含两个独立的Name对象只不过这两个Name对象具有“同样”的值。
Component的值为空从语义学上来讲是<emphasis>专有的(ad hoc)</emphasis>。 每当 组件的值可以为空,其定义如下。
重新加载一个包含组件的对象,如果component的所有字段为空那么将Hibernate将假定整个component为 每当Hibernate重新加载一个包含组件的对象,如果该组件的所有字段为空Hibernate将假定整个组件为空。
空。对于绝大多数目的,这样假定是没有问题的。 在大多数情况下,这样假定应该是没有问题的。
</para> </para>
<para> <para>
Component的属性可以是Hibernate类型包括Collections, many-to-one 关联, 以及其它Component 组件的属性可以是任意一种Hibernate类型包括集合, 多对多关联,
等等。嵌套Component不应该作为特殊的应用被考虑(Nested components should not be considered 以及其它组件等等)。嵌套组件不应该被当作一种特殊的应用(Nested components should not be considered an
an exotic usage)。 Hibernate趋向于支持设计细致(fine-grained)的对象模型。 exotic usage)。 Hibernate倾向于支持细致的(fine-grained)对象模型。
</para> </para>
<para> <para>
<literal>&lt;component&gt;</literal> 元素还允许有 <literal>&lt;parent&gt;</literal>子元素 用来表明component类中的一个属性返回包含它的实体的引用。 <literal>&lt;component&gt;</literal> 元素还允许有 <literal>&lt;parent&gt;</literal>子元素用来表明component类中的一个属性是指向包含它的实体的引用。
</para> </para>
<programlisting><![CDATA[<class name="eg.Person" table="person"> <programlisting><![CDATA[<class name="eg.Person" table="person">
<id name="Key" column="pid" type="string"> <id name="Key" column="pid" type="string">
<generator class="uuid"/> <generator class="uuid"/>
</id> </id>
<property name="birthday" type="date"/> <property name="birthday" type="date">
<component name="Name" class="eg.Name" unique="true">> <component name="Name" class="eg.Name" unique="true">
<parent name="namedPerson"/> <!-- reference back to the Person --> <parent name="namedPerson"/> <!-- reference back to the Person -->
<property name="initial"/> <property name="initial"/>
<property name="first"/> <property name="first"/>
<property name="last"/> <property name="last"/>
</component> </component&gt;
</class>]]></programlisting> </class>]]></programlisting>
</sect1> </sect1>
<sect1 id="components-incollections" revision="1"> <sect1 id="components-incollections" revision="1">
<title>在集合中出现的依赖对象</title> <title>在集合中出现的依赖对象 (Collections of dependent objects)</title>
<para> <para>
Hibernate支持component的集合(例如: 一个元素是“姓名”这种类型的数组)。 你可以使用<literal>&lt;composite-element&gt;</literal>标签替代<literal>&lt;element&gt;</literal>标签来定义你的component集合。 Hibernate支持组件的集合(例如: 一个元素是姓名(Name)这种类型的数组)。
</para> 你可以使用<literal>&lt;composite-element&gt;</literal>标签替代<literal>&lt;element&gt;</literal>标签来定义你的组件集合。
</para>
<programlisting><![CDATA[<set name="someNames" table="some_names" lazy="true"> <programlisting><![CDATA[<set name="someNames" table="some_names" lazy="true">
<key column="id"/> <key column="id"/&gt;
<composite-element class="eg.Name"> <!-- class attribute required --> <composite-element class="eg.Name"> <!-- class attribute required -->
<property name="initial"/> <property name="initial"/>
<property name="first"/> <property name="first"/>
<property name="last"/> <property name="last"/>;
</composite-element> </composite-element>
</set>]]></programlisting> </set>]]></programlisting>
<para> <para>
注意,如果你决定定义一个元素是联合元素的<literal>Set</literal>,正确地实现<literal>equals()</literal><literal>hashCode()</literal>是非常重要的。 注意如果你定义的Set包含组合元素(composite-element),正确地实现<literal>equals()</literal><literal>hashCode()</literal>是非常重要的。
</para> </para>
<para> <para>
组合元素可以包含component但是不能包含集合。如果你的组合元素自身包含component, 必须使用<literal>&lt;nested-composite-element&gt;</literal>标签。这是一个相当特殊的案例 - 组合元素的集合自身可以包含component。 这个时候你就应该考虑一下使用one-to-many关联是否会更恰当。 尝试对这个组合元素重新建模为一个实体但是需要注意的是虽然Java模型和重新建模前 是一样的,关系模型和持久性语义上仍然存在轻微的区别。 组合元素可以包含组件,但是不能包含集合。如果你的组合元素自身包含组件, 你必须使用<literal>&lt;nested-composite-element&gt;</literal>标签。这是一个相当特殊的案例 - 在一个组件的集合里那些组件本身又可以包含其他的组件。这个时候你就应该考虑一下使用one-to-many关联是否会更恰当。
</para> 尝试对这个组合元素重新建模为一个实体但是需要注意的是虽然Java模型和重新建模前是一样的关系模型和持久性语义会有细微的变化。
</para>
<para> <para>
请注意如果你使用<literal>&lt;set&gt;</literal>标签,一个组合元素的映射不支持可能为空的属性. 当删除对象时, Hibernate必须使用每一个字段的来确定一条记录(在组合元素表中,没有单个的关键字段), 如果有为null的字段这样做就不可能了。你必须作出一个选择要么在组合元素中使用不能为空的属性 要么选择使用<literal>&lt;list&gt;</literal>, <literal>&lt;map&gt;</literal>,<literal>&lt;bag&gt;</literal> 或者 <literal>&lt;idbag&gt;</literal>而不是 <literal>&lt;set&gt;</literal> 请注意如果你使用<literal>&lt;set&gt;</literal>标签,一个组合元素的映射不支持可能为空的属性. 当删除对象时, Hibernate必须使用每一个字段的值来确定一条记录(在组合元素表中,没有单独的关键字段)
</para> 如果有为null的字段这样做就不可能了。你必须作出一个选择要么在组合元素中使用不能为空的属性要么选择使用<literal>&lt;list&gt;</literal>,<literal>&lt;map&gt;</literal>,<literal>&lt;bag&gt;</literal> 或者 <literal>&lt;idbag&gt;</literal>而不是 <literal>&lt;set&gt;</literal>
</para>
<para> <para>
组合元素有个特别的案例,是组合元素可以包含一个<literal>&lt;many-to-one&gt;</literal> 元素。类似这样的映射允许你映射一个many-to-mang关联表作为组合元素额外的字段。(A mapping like this allows you to map extra columns of a many-to-many association table to the composite element class.) 接下来的的例子是从<literal>Order</literal><literal>Item</literal>的一个多对多的关联关系,<literal>purchaseDate</literal>, <literal>price</literal><literal>quantity</literal> <literal>Item</literal>的关联属性 组合元素有个特别的用法是它可以包含一个<literal>&lt;many-to-one&gt;</literal>元素。类似这样的映射允许你将一个many-to-many关联表映射为组合元素的集合。(A mapping like this allows you to map extra columns of a many-to-many association table to the composite element class.) 接下来的的例子是从<literal>Order</literal><literal>Item</literal>的一个多对多的关联关系, 关联属性是 <literal>purchaseDate</literal>, <literal>price</literal><literal>quantity</literal>
</para> </para>
<programlisting><![CDATA[<class name="eg.Order" .... > <programlisting><![CDATA[<class name="eg.Order" .... >
.... ....
<set name="purchasedItems" table="purchase_items" lazy="true"> <set name="purchasedItems" table="purchase_items" lazy="true">
<key column="order_id"> <key column="order_id">
@ -168,14 +169,13 @@
</composite-element> </composite-element>
</set> </set>
</class>]]></programlisting> </class>]]></programlisting>
<para> <para>
当然,在另一方面无法存在指向purchase的关联因此不能实现双向关联查询。记住组建是值类型并且不允许共享关联。单个<literal>Purchase</literal> 可以放在包含<literal>Order</literal>的集合中,但它不能同时被<literal>Item</literal>关联 当然,当你定义Item时你无法引用这些purchase因此你无法实现双向关联查询。记住组件是值类型并且不允许共享引用。某一个特定的<literal>Purchase</literal> 可以放在<literal>Order</literal>的集合中,但它不能同时被<literal>Item</literal>引用
</para> </para>
<para>其实组合元素的这个用法可以扩展到三重或多重关联:</para>
<para>即使三重或多重管理都是可能的:</para> <programlisting><![CDATA[<class name="eg.Order" .... >
<programlisting><![CDATA[<class name="eg.Order" .... >
.... ....
<set name="purchasedItems" table="purchase_items" lazy="true"> <set name="purchasedItems" table="purchase_items" lazy="true">
<key column="order_id"> <key column="order_id">
@ -186,52 +186,51 @@
</set> </set>
</class>]]></programlisting> </class>]]></programlisting>
<para>
在查询中,表达组合元素的语法和关联到其他实体的语法是一样的。
</para>
</sect1>
<sect1 id="components-asmapindex">
<title>组件作为Map的索引Components as Map indices </title>
<para>
<literal>&lt;composite-map-key&gt;</literal>元素允许你映射一个组件类作为一个<literal>Map</literal>的key前提是你必须正确的在这个类中重写了<literal>hashCode()</literal><literal>equals()</literal>方法。
</para>
</sect1>
<sect1 id="components-compositeid" revision="1">
<title>组件作为联合标识符(Components as composite identifiers)</title>
<para>
你可以使用一个组件作为一个实体类的标识符。 你的组件类必须满足以下要求:
</para>
<itemizedlist spacing="compact">
<listitem>
<para> <para>
在查询中,组合元素使用的语法是和关联到其他实体的语法一样的。 它必须实现<literal>java.io.Serializable</literal>接口
</para> </para>
</listitem>
</sect1> <listitem>
<sect1 id="components-asmapindex">
<title>组件作为Map的索引Components as Map indices </title>
<para> <para>
<literal>&lt;composite-map-key&gt;</literal>元素允许你映射一个Component类作为<literal>Map</literal>的key 但是你必须确定你正确的在这个类中重写了<literal>hashCode()</literal><literal>equals()</literal>方法。 它必须重新实现<literal>equals()</literal><literal>hashCode()</literal>方法, 始终和组合关键字在数据库中的概念保持一致
</para> </para>
</sect1> </listitem>
</itemizedlist>
<sect1 id="components-compositeid" revision="1"> <para>
<title>组件作为联合标识符(Components as composite identifiers)</title> <emphasis>注意在Hibernate3中第二个要求并非是Hibernate强制必须的。但最好这样做。</emphasis>
</para>
<para> <para>
你可以使用一个component作为一个实体类的标识符。 你的component类必须满足以下要求 你不能使用一个<literal>IdentifierGenerator</literal>产生组合关键字。一个应用程序必须分配它自己的标识符。
</para> </para>
<itemizedlist spacing="compact"> <para>
<listitem> 使用<literal>&lt;composite-id&gt;</literal> 标签(并且内嵌<literal>&lt;key-property&gt;</literal>元素)代替通常的<literal>&lt;id&gt;</literal>标签。比如,<literal>OrderLine</literal>类具有一个主键,这个主键依赖于<literal>Order</literal>的(联合)主键。
<para> </para>
它必须实现<literal>java.io.Serializable</literal>接口
</para>
</listitem>
<listitem>
<para>
它必须重新实现<literal>equals()</literal><literal>hashCode()</literal>方法, 始终和组合关键字在数据库中的概念保持一致
</para>
</listitem>
</itemizedlist>
<para>
<emphasis>注意在Hibernate3中第二种要求并非是Hibernate强制必须的。但最好这样做。</emphasis>
</para>
<para>
你不能使用一个<literal>IdentifierGenerator</literal>产生组合关键字。作为替代应用程序必须分配它自己的标识符。
</para>
<para>
使用<literal>&lt;composite-id&gt;</literal> 标签(并且内嵌<literal>&lt;key-property&gt;</literal>元素)代替通常的<literal>&lt;id&gt;</literal>标签。 比如,<literal>OrderLine</literal>类具有一个依赖<literal>Order</literal>的(联合)主键的主键。
</para>
<programlisting><![CDATA[<class name="OrderLine"> <programlisting><![CDATA[<class name="OrderLine">
@ -252,10 +251,9 @@
</class>]]></programlisting> </class>]]></programlisting>
<para> <para>
现在,任何指向<literal>OrderLine</literal>的外键都是复合的。在你的映射文件中,必须为其他类也这样声明。例如,一个指向<literal>OrderLine</literal>的关联可能被这样映射:
现在,任何关联到<literal>OrderLine</literal> 的外键都是复合的。在你的映射文件中,必须为其他类也这样声明。指向<literal>OrderLine</literal>的关联可能被这样映射: </para>
</para>
<programlisting><![CDATA[<many-to-one name="orderLine" class="OrderLine"> <programlisting><![CDATA[<many-to-one name="orderLine" class="OrderLine">
<!-- the "class" attribute is optional, as usual --> <!-- the "class" attribute is optional, as usual -->
@ -264,15 +262,13 @@
<column name="customerId"/> <column name="customerId"/>
</many-to-one>]]></programlisting> </many-to-one>]]></programlisting>
<para> <para>
(注意在各个地方<literal>&lt;column&gt;</literal>标签都是<literal>column</literal>属性的替代写法。)
</para>
(注意在各个地方<literal>&lt;column&gt;</literal>标签都是<literal>column</literal>属性的替代写法。) <para>
</para> 指向<literal>OrderLine</literal><literal>多对多</literal>关联也使用联合外键:
</para>
<para>
指向<literal>OrderLine</literal><literal>多对多</literal>关联也使用联合外键:
</para>
<programlisting><![CDATA[<set name="undeliveredOrderLines"> <programlisting><![CDATA[<set name="undeliveredOrderLines">
<key column name="warehouseId"/> <key column name="warehouseId"/>
@ -283,9 +279,9 @@
</many-to-many> </many-to-many>
</set>]]></programlisting> </set>]]></programlisting>
<para> <para>
<literal>Order</literal>中, <literal>OrderLine</literal>的集合则是这样: <literal>Order</literal>中,<literal>OrderLine</literal>的集合则是这样:
</para> </para>
<programlisting><![CDATA[<set name="orderLines" inverse="true"> <programlisting><![CDATA[<set name="orderLines" inverse="true">
<key> <key>
@ -295,13 +291,13 @@
<one-to-many class="OrderLine"/> <one-to-many class="OrderLine"/>
</set>]]></programlisting> </set>]]></programlisting>
<para> <para>
(与通常一样,<literal>&lt;one-to-many&gt;</literal>元素不声明任何列.) (与通常一样,<literal>&lt;one-to-many&gt;</literal>元素不声明任何列.)
</para> </para>
<para> <para>
假若<literal>OrderLine</literal>本身拥有一个集合,它也具有组合外键。 假若<literal>OrderLine</literal>本身拥有一个集合,它也具有组合外键。
</para> </para>
<programlisting><![CDATA[<class name="OrderLine"> <programlisting><![CDATA[<class name="OrderLine">
.... ....
@ -319,13 +315,14 @@
</set> </set>
</class>]]></programlisting> </class>]]></programlisting>
</sect1> </sect1>
<sect1 id="components-dynamic" revision="1"> <sect1 id="components-dynamic" revision="1">
<title>动态组件 Dynamic components</title> <title>动态组件 Dynamic components</title>
<para>
你甚至可以映射<literal>Map</literal>类型的属性: <para>
</para> 你甚至可以映射<literal>Map</literal>类型的属性:
</para>
<programlisting><![CDATA[<dynamic-component name="userAttributes"> <programlisting><![CDATA[<dynamic-component name="userAttributes">
<property name="foo" column="FOO" type="string"/> <property name="foo" column="FOO" type="string"/>
@ -333,11 +330,10 @@
<many-to-one name="baz" class="Baz" column="BAZ_ID"/> <many-to-one name="baz" class="Baz" column="BAZ_ID"/>
</dynamic-component>]]></programlisting> </dynamic-component>]]></programlisting>
<para> <para>
<literal>&lt;dynamic-component&gt;</literal>映射的语义上来讲,它和<literal>&lt;component&gt;</literal>是相同的。 <literal>&lt;dynamic-component&gt;</literal>映射的语义上来讲,它和<literal>&lt;component&gt;</literal>是相同的。
这种映射类型的优点在于通过修改映射文件,就可以具有在部署时检测真实属性的能力.利用一个DOM解析器是有可能在运行时刻操作映射文件的。 这种映射类型的优点在于通过修改映射文件就可以具有在部署时检测真实属性的能力。利用一个DOM解析器也可以在程序运行时操作映射文件。
更好的是,你可以通过<literal>Configuration</literal>对象来访问或者修改Hibernate的运行时元模型。 更好的是,你可以通过<literal>Configuration</literal>对象来访问或者修改Hibernate的运行时元模型。
</para> </para>
</sect1> </sect1>
</chapter> </chapter>

View File

@ -8,7 +8,7 @@
由于Hibernate是为了能在各种不同环境下工作而设计的, 因此存在着大量的配置参数. 幸运的是多数配置参数都 由于Hibernate是为了能在各种不同环境下工作而设计的, 因此存在着大量的配置参数. 幸运的是多数配置参数都
有比较直观的默认值, 并有随Hibernate一同分发的配置样例<literal>hibernate.properties</literal> 有比较直观的默认值, 并有随Hibernate一同分发的配置样例<literal>hibernate.properties</literal>
(位于<literal>etc/</literal>)来展示各种配置选项. 所需做的仅仅是将这个样例文件复制到类路径 (位于<literal>etc/</literal>)来展示各种配置选项. 所需做的仅仅是将这个样例文件复制到类路径
(classpath)下做一些自定义的修改. (classpath)下做一些自定义的修改.
</para> </para>
<sect1 id="configuration-programmatic" revision="1"> <sect1 id="configuration-programmatic" revision="1">
@ -90,11 +90,11 @@
</orderedlist> </orderedlist>
<para> <para>
如果想尽快体验Hbernate, <literal>hibernate.properties</literal>是最简单的方式. 如果想尽快体验Hibernate, <literal>hibernate.properties</literal>是最简单的方式.
</para> </para>
<para> <para>
<literal>Configuration</literal>实例是一个启动期间startup-time对象, <literal>Configuration</literal>实例被设计成启动期间startup-time对象,
一旦<literal>SessionFactory</literal>创建完成它就被丢弃了. 一旦<literal>SessionFactory</literal>创建完成它就被丢弃了.
</para> </para>
@ -211,9 +211,9 @@
<para> <para>
但Hibernate自带的连接池算法相当不成熟. 但Hibernate自带的连接池算法相当不成熟.
它只是为了让你快些上手<emphasis>,不适合用于产品系统</emphasis>或性能测试中。 它只是为了让你快些上手<emphasis>不适合用于产品系统</emphasis>或性能测试中。
出于最佳性能和稳定性考虑你应该使用第三方的连接池。只需要连接池的特定设置替换 出于最佳性能和稳定性考虑你应该使用第三方的连接池。只需要用特定连接池的设置替换
<literal>hibernate.connection.pool_size</literal>。这将关闭Hibernate自带的连接池. <literal>hibernate.connection.pool_size</literal>即可。这将关闭Hibernate自带的连接池.
例如, 你可能会想用C3P0. 例如, 你可能会想用C3P0.
</para> </para>
@ -239,8 +239,8 @@ hibernate.c3p0.max_statements=50
hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting> hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<para> <para>
为了能在应用程序服务器(application server)中使用Hibernate, 应当总是将Hibernate 为了能在应用程序服务器(application server)中使用Hibernate, 应当总是将Hibernate
配置成注册在JNDI中的<literal>Datasource</literal>处获得连接,你至少需要设置下列属性中的一个: 配置成注册在JNDI中的<literal>Datasource</literal>处获得连接,你至少需要设置下列属性中的一个:
</para> </para>
<table frame="topbot"> <table frame="topbot">
@ -306,7 +306,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
</table> </table>
<para> <para>
里有一个使用应用程序服务器JNDI数据源的<literal>hibernate.properties</literal>样例文件: 是一个使用应用程序服务器提供的JNDI数据源的<literal>hibernate.properties</literal>样例文件:
</para> </para>
<programlisting><![CDATA[hibernate.connection.datasource = java:/comp/env/jdbc/test <programlisting><![CDATA[hibernate.connection.datasource = java:/comp/env/jdbc/test
@ -317,12 +317,12 @@ hibernate.transaction.manager_lookup_class = \
hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting> hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<para> <para>
从JNDI数据源获得的JDBC连接将自动参与应用程序服务器中容器管理的事务(container-managed transactions)中去. 从JNDI数据源获得的JDBC连接将自动参与应用程序服务器中容器管理的事务(container-managed transactions)中去.
</para> </para>
<para> <para>
任何连接(connection)配置属性的属性名要以"<literal>hibernate.connnection</literal>"前缀开头. 任何连接(connection)属性的属性名要以"<literal>hibernate.connnection</literal>"开头.
例如, 你可能会使用<literal>hibernate.connection.charSet</literal>来指定<literal>charSet</literal>. 例如, 你可能会使用<literal>hibernate.connection.charSet</literal>来指定字符集<literal>charSet</literal>.
</para> </para>
<para> <para>
@ -344,7 +344,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<para> <para>
<emphasis>警告: 其中一些属性是"系统级(system-level)的".</emphasis> <emphasis>警告: 其中一些属性是"系统级(system-level)的".</emphasis>
系统级属性可以通过<literal>java -Dproperty=value</literal> 系统级属性只能通过<literal>java -Dproperty=value</literal>
<literal>hibernate.properties</literal>来设置, 而<emphasis>不能</emphasis>用上面描述的其他方法来设置. <literal>hibernate.properties</literal>来设置, 而<emphasis>不能</emphasis>用上面描述的其他方法来设置.
</para> </para>
@ -375,7 +375,8 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<para> <para>
<emphasis role="strong">取值</emphasis> <emphasis role="strong">取值</emphasis>
<literal>full.classname.of.Dialect</literal> <literal>full.classname.of.Dialect</literal>
</para>
</para>
</entry> </entry>
</row> </row>
<row> <row>
@ -420,7 +421,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<literal>hibernate.default_catalog</literal> <literal>hibernate.default_catalog</literal>
</entry> </entry>
<entry> <entry>
在生成的SQL中, 将给定的catalog附加于全限定名的表名上. 在生成的SQL中, 将给定的catalog附加于全限定名的表名上.
<para> <para>
<emphasis role="strong">取值</emphasis> <emphasis role="strong">取值</emphasis>
<literal>CATALOG_NAME</literal> <literal>CATALOG_NAME</literal>
@ -781,7 +782,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<literal>hibernate.cache.query_cache_factory</literal> <literal>hibernate.cache.query_cache_factory</literal>
</entry> </entry>
<entry> <entry>
自定义实现<literal>QueryCache</literal>接口的类名, 自定义实现<literal>QueryCache</literal>接口的类名,
默认为内建的<literal>StandardQueryCache</literal>. 默认为内建的<literal>StandardQueryCache</literal>.
<para> <para>
<emphasis role="strong">取值</emphasis> <emphasis role="strong">取值</emphasis>
@ -925,8 +926,8 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<literal>hibernate.current_session_context_class</literal> <literal>hibernate.current_session_context_class</literal>
</entry> </entry>
<entry> <entry>
界定"当前" 为"当前"
<literal>Session</literal>指定一个策略。关于内置策略的详情,请参见<xref linkend="architecture-current-session"/> <literal>Session</literal>指定一个(自定义的)策略。关于内置策略的详情,请参见<xref linkend="architecture-current-session"/>
<para> <para>
<emphasis role="strong">eg.</emphasis> <emphasis role="strong">eg.</emphasis>
<literal>jta</literal> | <literal>thread</literal> | <literal>jta</literal> | <literal>thread</literal> |
@ -965,7 +966,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<literal>hibernate.hbm2ddl.auto</literal> <literal>hibernate.hbm2ddl.auto</literal>
</entry> </entry>
<entry> <entry>
<literal>SessionFactory</literal>创建时,自动检查数据库或者将数据库schema的DDL导出到数据库. 使用 <literal>SessionFactory</literal>创建时,自动检查数据库或者将数据库schema的DDL导出到数据库. 使用
<literal>create-drop</literal>时,在显式关闭<literal>SessionFactory</literal>将drop掉数据库schema. <literal>create-drop</literal>时,在显式关闭<literal>SessionFactory</literal>将drop掉数据库schema.
<para> <para>
<emphasis role="strong">取值</emphasis> <emphasis role="strong">取值</emphasis>
@ -997,7 +998,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
</title> </title>
<para> <para>
你应当总是为你的数据库属性<literal>hibernate.dialect</literal>设置正确的 你应当总是为你的数据库<literal>hibernate.dialect</literal>属性设置正确的
<literal>org.hibernate.dialect.Dialect</literal>子类. 如果你指定一种方言, <literal>org.hibernate.dialect.Dialect</literal>子类. 如果你指定一种方言,
Hibernate将为上面列出的一些属性使用合理的默认值, 为你省去了手工指定它们的功夫. Hibernate将为上面列出的一些属性使用合理的默认值, 为你省去了手工指定它们的功夫.
</para> </para>
@ -1096,8 +1097,8 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
</title> </title>
<para> <para>
如果你的数据库支持ANSI, Oracle或Sybase风格的外连接, <emphasis>外连接抓取</emphasis>常能通过限制往返数据库次数 如果你的数据库支持ANSI, Oracle或Sybase风格的外连接, <emphasis>外连接抓取</emphasis>常能通过限制往返数据库次数
(更多的工作交由数据库自己来完成)来提高效率. 外连接允许在单个<literal>SELECT</literal>SQL语句中 (更多的工作交由数据库自己来完成)来提高效率. 外连接抓取允许在单个<literal>SELECT</literal>SQL语句中
通过many-to-one, one-to-many, many-to-many和one-to-one关联获取连接对象的整个对象图. 通过many-to-one, one-to-many, many-to-many和one-to-one关联获取连接对象的整个对象图.
</para> </para>
@ -1283,7 +1284,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<para> <para>
在使用Hibernate开发应用程序时, 你应当总是为<literal>org.hibernate.SQL</literal> 在使用Hibernate开发应用程序时, 你应当总是为<literal>org.hibernate.SQL</literal>
开启<literal>debug</literal>级别的日志记录,或者开启<literal>hibernate.show_sql</literal>属性来代替它. 开启<literal>debug</literal>级别的日志记录,或者开启<literal>hibernate.show_sql</literal>属性。
</para> </para>
</sect1> </sect1>
@ -1328,7 +1329,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<para> <para>
另一个配置方法是在<literal>hibernate.cfg.xml</literal>文件中指定一套完整的配置. 另一个配置方法是在<literal>hibernate.cfg.xml</literal>文件中指定一套完整的配置.
这个文件可以当成<literal>hibernate.properties</literal>的替代。 若两个文件同时存在,它将重载前者的属性. 这个文件可以当成<literal>hibernate.properties</literal>的替代。 若两个文件同时存在,它将覆盖前者的属性.
</para> </para>
<para> <para>
@ -1406,7 +1407,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<listitem> <listitem>
<para> <para>
<emphasis>容器管理的数据源(Container-managed datasources)</emphasis>: <emphasis>容器管理的数据源(Container-managed datasources)</emphasis>:
Hibernate能通过容器管理由JNDI提供的JDBC连接. 通常, 特别是当处理多个数据源的分布式事务的时候, Hibernate能使用通过容器管理,并由JNDI提供的JDBC连接. 通常, 特别是当处理多个数据源的分布式事务的时候,
由一个JTA兼容的<literal>TransactionManager</literal>和一个 由一个JTA兼容的<literal>TransactionManager</literal>和一个
<literal>ResourceManager</literal>来处理事务管理(CMT, 容器管理的事务). 当然你可以通过 <literal>ResourceManager</literal>来处理事务管理(CMT, 容器管理的事务). 当然你可以通过
编程方式来划分事务边界(BMT, Bean管理的事务). 或者为了代码的可移植性,你也也许会想使用可选的 编程方式来划分事务边界(BMT, Bean管理的事务). 或者为了代码的可移植性,你也也许会想使用可选的
@ -1430,7 +1431,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<emphasis>JTA Session绑定:</emphasis> Hibernate <literal>Session</literal> <emphasis>JTA Session绑定:</emphasis> Hibernate <literal>Session</literal>
可以自动绑定到JTA事务作用的范围. 只需简单地从JNDI查找<literal>SessionFactory</literal>并获得当前的 可以自动绑定到JTA事务作用的范围. 只需简单地从JNDI查找<literal>SessionFactory</literal>并获得当前的
<literal>Session</literal>. 当JTA事务完成时, 让Hibernate来处理 <literal>Session</literal>. 当JTA事务完成时, 让Hibernate来处理
<literal>Session</literal>的清洗(flush)与关闭. 在EJB的部署描述符中事务边界是声明式的(CMT),或者自行编程(BMT/UserTransaction). <literal>Session</literal>的清洗(flush)与关闭. 事务的划分可以是声明式的(CMT),也可以是编程式的(BMT/UserTransaction).
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
@ -1440,7 +1441,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<para> <para>
<emphasis>JMX部署:</emphasis> 如果你使用支持JMX应用程序服务器(如, JBoss AS), 那么你可以选择将Hibernate部署成托管MBean. <emphasis>JMX部署:</emphasis> 如果你使用支持JMX应用程序服务器(如, JBoss AS), 那么你可以选择将Hibernate部署成托管MBean.
这将为你省去一行从<literal>Configuration</literal>构建<literal>SessionFactory</literal>的启动代码. 这将为你省去一行从<literal>Configuration</literal>构建<literal>SessionFactory</literal>的启动代码.
容器将启动你的<literal>HibernateService</literal>, 并完美地处理好服务间的依赖关系 (在Hibernate启动前数据源必须是可用的等等). 容器将启动你的<literal>HibernateService</literal>, 并完美地处理好服务间的依赖关系 (在Hibernate启动前数据源必须是可用的等等).
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
@ -1466,7 +1467,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
</para> </para>
<para> <para>
存在着三个标准(内建)的选择: 三个标准(内建)的选择:
</para> </para>
<variablelist spacing="compact"> <variablelist spacing="compact">
@ -1610,7 +1611,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<title>在JTA环境下使用Current Session context (当前session上下文)管理</title> <title>在JTA环境下使用Current Session context (当前session上下文)管理</title>
<para> <para>
在Hibernate中管理<literal>Session</literal>和transaction最好的方法是自动的"当前"<literal>Session</literal>管理。请参见<xref linkend="architecture-current-session">current sessions</xref>一节的讨论。使用<literal>"jta"</literal>session上下文假若在当前JTA事务中还没有Hibernate<literal>Session</literal>关联,第一次<literal>sessionFactory.getCurrentSession()</literal>调用会启动一个Session,并关联到当前的JTA事务。在<literal>"jta"</literal>上下文中用<literal>getCurrentSession()</literal>获得的<literal>Session</literal>会被设置为在transaction关闭的时候自动flush清洗、在transaction关闭之后自动关闭每句句之后主动释放JDBC连接。这就可以根据JTA事务的生命周期来管理与之关联的<literal>Session</literal>,用户代码中就可以不再考虑这些管理。你的代码可以通过<literal>UserTransaction</literal>用编程方式使用JTA或者(我们建议为了便于移植代码使用Hibernate的<literal>Transaction</literal> API来设置transaction边界。如果你的代码运行EJB容器中建议对CMT使用声明式事务声明。 在Hibernate中管理<literal>Session</literal>和transaction最好的方法是自动的"当前"<literal>Session</literal>管理。请参见<xref linkend="architecture-current-session">contextual sessions</xref>一节的讨论。使用<literal>"jta"</literal>session上下文假若在当前JTA事务中还没有Hibernate<literal>Session</literal>关联,第一次<literal>sessionFactory.getCurrentSession()</literal>调用会启动一个Session,并关联到当前的JTA事务。在<literal>"jta"</literal>上下文中<literal>getCurrentSession()</literal>获得的<literal>Session</literal>会被设置为在transaction关闭的时候自动flush清洗、在transaction关闭之后自动关闭每句句之后主动释放JDBC连接。这就可以根据JTA事务的生命周期来管理与之关联的<literal>Session</literal>,用户代码中就可以不再考虑这些管理。你的代码可以通过<literal>UserTransaction</literal>用编程方式使用JTA或者(我们建议为了便于移植代码使用Hibernate的<literal>Transaction</literal> API来设置transaction边界。如果你的代码运行EJB容器中建议对CMT使用声明式事务声明。
</para> </para>
</sect2> </sect2>
@ -1620,7 +1621,7 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
</title> </title>
<para> <para>
为了将<literal>SessionFactory</literal>注册到JNDI中<literal>cfg.buildSessionFactory()</literal>这行代码仍需在某处被执行. 为了将<literal>SessionFactory</literal>注册到JNDI中<literal>cfg.buildSessionFactory()</literal>这行代码仍需在某处被执行.
你可在一个<literal>static</literal>初始化块(像<literal>HibernateUtil</literal>中的那样)中执行它或将Hibernate部署为一个<emphasis>托管的服务</emphasis>. 你可在一个<literal>static</literal>初始化块(像<literal>HibernateUtil</literal>中的那样)中执行它或将Hibernate部署为一个<emphasis>托管的服务</emphasis>.
</para> </para>
@ -1675,9 +1676,9 @@ hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
<para> <para>
这个文件是部署在<literal>META-INF</literal>目录下的, 并会被打包到以<literal>.sar</literal> (service archive)为扩展名的JAR文件中. 这个文件是部署在<literal>META-INF</literal>目录下的, 并会被打包到以<literal>.sar</literal> (service archive)为扩展名的JAR文件中.
同时,你需要打包Hibernate, 它所需要的第三方库, 你编译好的持久化类及你的映射定义文件打包进同一个文档. 同时,你需要将Hibernate、它所需要的第三方库、你编译好的持久化类以及你的映射定义文件打包进同一个文档.
你的企业Bean(一般为会话Bean)可能会被打包成它们自己的JAR文件, 但你也许会将EJB JAR文件一同包含进能独立(热)部署的主服务文档. 你的企业Bean(一般为会话Bean)可能会被打包成它们自己的JAR文件, 但你也许会将EJB JAR文件一同包含进能独立(热)部署的主服务文档.
咨询JBoss AS文档以了解更多的JMX服务与EJB部署的信息. 参考JBoss AS文档以了解更多的JMX服务与EJB部署的信息.
</para> </para>
</sect2> </sect2>

View File

@ -51,9 +51,8 @@
</para> </para>
<para> <para>
在不同的映射文件中定义 <literal>subclass</literal>, <literal>union-subclass</literal>, 在多个映射文件中,可以直接在<literal>hibernate-mapping</literal>根下定义<literal>subclass</literal><literal>union-subclass</literal><literal>joined-subclass</literal>。也就是说你可以仅加入一个新的映射文件来扩展类层次。你必须在subclass的映射中指明<literal>extends</literal>属性给出一个之前定义的超类的名字。注意在以前这一功能对映射文件的顺序有严格的要求从Hibernate 3开始使用extends关键字的时侯对映射文件的顺序不再有要求但在每个映射文件里超类必须在子类之前定义。
<literal>joined-subclass</literal>是被允许的,只需直接定义在<literal>hibernate-mapping</literal>之下 。也就是说你可以仅加入一个新的映射文件就扩展类层次。你必须在subclass的映射中指明<literal>extends</literal>属性给出一个之前定义的超类的名字。注意以前这一功能对映射文件的顺序有严格的要求。自从Hibernate 3开始当使用extends关键字的时候映射文件的顺序不再有影响。但在每个映射文件本身之中顺序还是必须超类在前子类在后。 </para>
</para>
<programlisting><![CDATA[ <programlisting><![CDATA[
<hibernate-mapping> <hibernate-mapping>
@ -142,7 +141,7 @@
注意对“每个子类一张表”的映射策略Hibernate的实现不需要辨别字段而其他 注意对“每个子类一张表”的映射策略Hibernate的实现不需要辨别字段而其他
的对象/关系映射工具使用了一种不同于Hibernate的实现方法该方法要求在超类 的对象/关系映射工具使用了一种不同于Hibernate的实现方法该方法要求在超类
表中有一个类型辨别字段(type discriminator column)。Hibernate采用的方法更 表中有一个类型辨别字段(type discriminator column)。Hibernate采用的方法更
难实现,但从关系(数据库)这点上来看,按理说它更正确。若你愿意使用带有辨别字 难实现,但从关系(数据库)的角度来看,按理说它更正确。若你愿意使用带有辨别字
段的“每个子类一张表”的策略,你可以结合使用<literal>&lt;subclass&gt;</literal> 段的“每个子类一张表”的策略,你可以结合使用<literal>&lt;subclass&gt;</literal>
<literal>&lt;join&gt;</literal>,如下所示: <literal>&lt;join&gt;</literal>,如下所示:
</para> </para>
@ -408,7 +407,7 @@
<entry>多态 <literal>load()/get()</literal></entry> <entry>多态 <literal>load()/get()</literal></entry>
<entry>多态查询</entry> <entry>多态查询</entry>
<entry>多态连接(join)</entry> <entry>多态连接(join)</entry>
<entry>外连接(Outer join)</entry> <entry>外连接(Outer join)</entry>
</row> </row>
</thead> </thead>
<tbody> <tbody>

View File

@ -10,8 +10,8 @@
<para> <para>
如果这些持久化类遵循一些简单的规则Hibernate能够工作得最好,这些规则被称作, 如果这些持久化类遵循一些简单的规则Hibernate能够工作得更好,这些规则也被称作
简单传统Java对象(POJO:Plain Old Java Object)编程模型。但是这些规则没有一个是必需的。 简单传统Java对象(POJO:Plain Old Java Object)编程模型。但是这些规则并不是必需的。
实际上Hibernate3对于你的持久化类几乎不做任何设想。你可以用其他的方法来表达领域模型 实际上Hibernate3对于你的持久化类几乎不做任何设想。你可以用其他的方法来表达领域模型
比如,使用<literal>Map</literal>实例的树型结构。 比如,使用<literal>Map</literal>实例的树型结构。
</para> </para>
@ -115,7 +115,7 @@ public class Cat {
<literal>Cat</literal>有一个无参数的构造方法。所有的持久化类都必须有一个 <literal>Cat</literal>有一个无参数的构造方法。所有的持久化类都必须有一个
默认的构造方法可以不是public的这样的话Hibernate就可以使用 默认的构造方法可以不是public的这样的话Hibernate就可以使用
<literal>Constructor.newInstance()</literal>来实例化它们。 <literal>Constructor.newInstance()</literal>来实例化它们。
我们建议在Hibernate中为了运行期代理的生成构造方法至少是 我们强烈建议在Hibernate中为了运行期代理的生成构造方法至少是
<emphasis>包(package)</emphasis>内可见的。 <emphasis>包(package)</emphasis>内可见的。
</para> </para>
@ -128,14 +128,14 @@ public class Cat {
<literal>Cat</literal>有一个属性叫做<literal>id</literal>。这个属性映射数据库表的主 <literal>Cat</literal>有一个属性叫做<literal>id</literal>。这个属性映射数据库表的主
键字段。这个属性可以叫任何名字,其类型可以是任何的原始类型、原始类型的包装类型、 键字段。这个属性可以叫任何名字,其类型可以是任何的原始类型、原始类型的包装类型、
<literal>java.lang.String</literal> 或者是 <literal>java.util.Date</literal> <literal>java.lang.String</literal> 或者是 <literal>java.util.Date</literal>
(如果你的老式数据库表有联合主键,你甚至可以用一个用户自定义的类,该类拥有这些类型 (如果你的遗留数据库表有联合主键,你甚至可以用一个用户自定义的类,该类拥有这些类型
的属性。参见后面的关于联合标识符的章节。) 的属性。参见后面的关于联合标识符的章节。)
</para> </para>
<para> <para>
标识符属性是可选的。可以不用管它让Hibernate内部来追踪对象的识别。 标识符属性是可选的。可以不用管它让Hibernate内部来追踪对象的识别。
不推荐使用这个属性 但是我们并不推荐这样做
</para> </para>
<para> <para>
@ -146,7 +146,7 @@ public class Cat {
<listitem> <listitem>
<para> <para>
托管对象的传播性重新和session关联(级联更新或级联合并) 托管对象的传播性再连接(级联更新或级联合并)
——参阅 <xref linkend="objectstate-transitive"/> ——参阅 <xref linkend="objectstate-transitive"/>
</para> </para>
@ -165,8 +165,8 @@ public class Cat {
<para> <para>
我们建议你对持久化类声明命名一致的标识属性。我们还建议你使用一 我们建议你对持久化类声明命名一致的标识属性。我们还建议你使用一
个可以为空(也就是说,不是原始类型)的类型。 个可以为空(也就是说,不是原始类型)的类型。
</para> </para>
</sect2> </sect2>
@ -185,28 +185,28 @@ public class Cat {
</para> </para>
<para> <para>
你也应该避免在非final类中声明 <literal>public final</literal>的方法。如果你想使用一 你也应该避免在非final类中声明 <literal>public final</literal>的方法。如果你想使用一
个有<literal>public final</literal>方法的类,你必须通过设置<literal>lazy="false"</literal> 个有<literal>public final</literal>方法的类,你必须通过设置<literal>lazy="false"</literal>
来明确的禁用代理。 来明确地禁用代理。
</para> </para>
</sect2> </sect2>
<sect2 id="persistent-classes-pojo-accessors" revision="2"> <sect2 id="persistent-classes-pojo-accessors" revision="2">
<title>为持久化字段声明访问器(accessors)和是否可变的标志(mutators)(可选)</title> <title>为持久化字段声明访问器(accessors)和是否可变的标志(mutators)(可选)</title>
<para> <para>
<literal>Cat</literal>为它的所有持久化字段声明了访问方法。很多其他ORM工具直接对 <literal>Cat</literal>为它的所有持久化字段声明了访问方法。很多其他ORM工具直接对
实例变量进行持久化。我们相信,在关系数据库schema和类的内部数据之间引入间接层(原文为"非直接"indirection)会好一些。默认情况下Hibernate持久化JavaBeans风格的属性认可如下形式的方法名: 实例变量进行持久化。我们相信在关系数据库schema和类的内部数据结构之间引入间接层(原文为"非直接"indirection)会好一些。默认情况下Hibernate持久化JavaBeans风格的属性认可
<literal>getFoo</literal>, <literal>isFoo</literal><literal>setFoo</literal> <literal>getFoo</literal><literal>isFoo</literal><literal>setFoo</literal>这种形式的方法名
如果需要,你总是可以切换特定的属性的指示字段的访问方法 如果需要,你可以对某些特定属性实行直接字段访问
</para> </para>
<para> <para>
属性<emphasis>不需要</emphasis>要声明为public的。Hibernate默认使用 属性<emphasis>不需要</emphasis>要声明为public的。Hibernate可以持久化一个有
<literal>protected</literal><literal>private</literal>的get/set方法对 <literal>default</literal><literal>protected</literal><literal>private</literal>的get/set方法对
属性进行持久化。 属性进行持久化。
</para> </para>
</sect2> </sect2>
</sect1> </sect1>
@ -254,8 +254,8 @@ public class DomesticCat extends Cat {
</itemizedlist> </itemizedlist>
<para> <para>
Hibernate保证持久化标识数据库的行和仅在特定会话范围内的Java标识是等值的。因此,一旦 Hibernate保证仅在特定会话范围内持久化标识数据库的行和Java标识是等价的。因此,一旦
我们混合了从不同会话中获取的实例,如果我们希望<literal>Set</literal>有明确的语义,我们 我们混合了从不同会话中获取的实例,如果希望<literal>Set</literal>有明确的语义,
须实现<literal>equals()</literal><literal>hashCode()</literal> 须实现<literal>equals()</literal><literal>hashCode()</literal>
</para> </para>
@ -264,16 +264,15 @@ public class DomesticCat extends Cat {
标识符的值。如果值相同,则两个对象对应于数据库的同一行,因此它们是相等的(如果都被添加到 标识符的值。如果值相同,则两个对象对应于数据库的同一行,因此它们是相等的(如果都被添加到
<literal>Set</literal>,则在<literal>Set</literal>中只有一个元素)。不幸的是,对生成的标识不能 <literal>Set</literal>,则在<literal>Set</literal>中只有一个元素)。不幸的是,对生成的标识不能
使用这种方法。Hibernate仅对那些持久化对象赋标识值一个新创建的实例将不会有任何标识值。此外 使用这种方法。Hibernate仅对那些持久化对象赋标识值一个新创建的实例将不会有任何标识值。此外
如果一个实例没有被保存(unsaved),并且在一个<literal>Set</literal>中,保存它将会给这个对象 如果一个实例没有被保存(unsaved),并且它当前正在一个<literal>Set</literal>中,保存它将会给这个对象
赋一个标识值。如果<literal>equals()</literal><literal>hashCode()</literal>是基于标识值 赋一个标识值。如果<literal>equals()</literal><literal>hashCode()</literal>是基于标识值
实现的,则其哈希码将会改变,违反<literal>Set</literal>的契约。建议去Hibernate的站点关于这个 实现的,则其哈希码将会改变,违反<literal>Set</literal>的契约。建议去Hibernate的站点阅读关于这个
问题的全部讨论。注意,这不是一个Hibernate问题而是一般的Java对象标识和相等的语义问题。 问题的全部讨论。注意,这不是Hibernate的问题而是一般的Java对象标识和Java对象等价的语义问题。
</para> </para>
<para> <para>
我们建议使用<emphasis>业务键值相等(Business key equality)</emphasis>来实现<literal>equals()</literal> 我们建议使用<emphasis>业务键值相等(Business key equality)</emphasis>来实现<literal>equals()</literal>
<literal>hashCode()</literal>。业务键值相等的意思是,<literal>equals()</literal>方法 <literal>hashCode()</literal>。业务键值相等的意思是,<literal>equals()</literal>方法
仅仅比较来自业务键的属性,一个业务键将标识在真实世界里(一个<emphasis>天生的</emphasis>候选键) 仅仅比较形成业务键的属性,它能在现实世界里标识我们的实例(是一个<emphasis>自然的</emphasis>候选码)。
的实例。
</para> </para>
<programlisting><![CDATA[public class Cat { <programlisting><![CDATA[public class Cat {
@ -300,8 +299,8 @@ public class DomesticCat extends Cat {
}]]></programlisting> }]]></programlisting>
<para> <para>
注意,业务键不必是象数据库的主键那样是固定不变的(参见<xref linkend="transactions-basics-identity"/>)。 注意,业务键不必像数据库的主键那样固定不变(参见<xref linkend="transactions-basics-identity"/>)。
对业务键而言,不可变或唯一的属性是好的候选 对业务键而言,不可变或唯一的属性是不错的选择
</para> </para>
</sect1> </sect1>
@ -309,11 +308,11 @@ public class DomesticCat extends Cat {
<sect1 id="persistent-classes-dynamicmodels"> <sect1 id="persistent-classes-dynamicmodels">
<title>动态模型(Dynamic models)</title> <title>动态模型(Dynamic models)</title>
<para> <para>
<emphasis>注意,以下特性在当前是基于实验考虑的,可能会在将来改变</emphasis> <emphasis>注意,以下特性在当前处于试验阶段,将来可能会有变化</emphasis>
</para> </para>
<para> <para>
运行期的持久化实体没有必要象POJO类或JavaBean对象一样表示。Hibernate也支持动态模型 运行期的持久化实体没有必要一定表示为像POJO类或JavaBean对象那样的形式。Hibernate也支持动态模型
(在运行期使用<literal>Map</literal><literal>Map</literal>和象DOM4J的树模型那 (在运行期使用<literal>Map</literal><literal>Map</literal>和象DOM4J的树模型那
样的实体表示。使用这种方法,你不用写持久化类,只写映射文件就行了。 样的实体表示。使用这种方法,你不用写持久化类,只写映射文件就行了。
</para> </para>
@ -327,7 +326,7 @@ public class DomesticCat extends Cat {
<para> <para>
下面是用<literal>Map</literal>来表示的例子。首先,在映射文件中,要声明 下面是用<literal>Map</literal>来表示的例子。首先,在映射文件中,要声明
<literal>entity-name</literal>来代替(或外加)一个类名。 <literal>entity-name</literal>来代替一个类名(或作为一种附属)
</para> </para>
<programlisting><![CDATA[<hibernate-mapping> <programlisting><![CDATA[<hibernate-mapping>
@ -397,9 +396,9 @@ tx.commit();
s.close();]]></programlisting> s.close();]]></programlisting>
<para> <para>
动态映射的好处是,使原型在不需要实体类实现的情况下,快速转变时间。然而,你无法进行 动态映射的好处是,变化所需要的时间少了,因为原型不需要实现实体类。然而,你无法进行
编译期的类型检查并可能由此会处理很多的运行期异常。幸亏有了Hibernate映射它使得数 编译期的类型检查并可能由此会处理很多的运行期异常。幸亏有了Hibernate映射它使得数
据库的schema能容易的规格化和合理化并允许稍后添加正确的领域模型的最新实现。 据库的schema能容易的规格化和合理化并允许稍后在此之上添加合适的领域模型实现。
</para> </para>
@ -440,11 +439,11 @@ dynamicSession.close()
<title>元组片断映射(Tuplizers)</title> <title>元组片断映射(Tuplizers)</title>
<para> <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.EntityTuplizer</literal><literal>org.hibernate.tuple.ComponentTuplizer</literal>接口。<literal>EntityTuplizer</literal>负责管理上面提到的实体的契约,而<literal>ComponentTuplizer</literal>则是针对组件
</para> </para>
<para> <para>
用户也可以插入其自定义的tuplizer。或许您需要一种特别的<literal>java.util.Map</literal>实现它不是在dynamic-map entity-mode时使用的 <literal>java.util.HashMap</literal> ;或许您需要与众不同的特别代理生成策略(proxy generation strategy)。通过自定义tuplizer实现这两个目标您都可以达到。Tuplizer定义被附加到它们期望管理的entity或者component映射。回到我们的customer entity例子: 用户也可以插入其自定义的tuplizer。或许您需要一种不同于dynamic-map entity-mode中使用的<literal>java.util.HashMap</literal><literal>java.util.Map</literal>实现;或许您需要与默认策略不同的代理生成策略(proxy generation strategy)。通过自定义tuplizer实现这两个目标您都可以达到。Tuplizer定义被附加到它们期望管理的entity或者component映射中。回到我们的customer entity例子
</para> </para>
<programlisting><![CDATA[<hibernate-mapping> <programlisting><![CDATA[<hibernate-mapping>
@ -487,7 +486,7 @@ public class CustomMapTuplizerImpl
</sect1> </sect1>
<para> <para>
TODO在property和proxy的包里用户扩展文件框架 TODOproperty和proxy包里的用户扩展框架文档
</para> </para>
</chapter> </chapter>

View File

@ -28,7 +28,7 @@
<para> <para>
<emphasis>瞬时(Transient)</emphasis> - 由<literal>new</literal>操作符创建且尚未与Hibernate <literal>Session</literal> <emphasis>瞬时(Transient)</emphasis> - 由<literal>new</literal>操作符创建且尚未与Hibernate <literal>Session</literal>
关联的对象被认定为瞬时(Transient)的。瞬时(Transient)对象不会被持久化到数据库中,也不会被赋予持久化标识(identifier)。 关联的对象被认定为瞬时(Transient)的。瞬时(Transient)对象不会被持久化到数据库中,也不会被赋予持久化标识(identifier)。
如果程序中没有保持对瞬时(Transient)对象的引用,它会被垃圾回收器(garbage collector)销毁。 如果瞬时(Transient)对象在程序中没有被引用,它会被垃圾回收器(garbage collector)销毁。
使用Hibernate <literal>Session</literal>可以将其变为持久(Persistent)状态。(Hibernate会自动执行必要的SQL语句) 使用Hibernate <literal>Session</literal>可以将其变为持久(Persistent)状态。(Hibernate会自动执行必要的SQL语句)
</para> </para>
@ -37,7 +37,7 @@
<para> <para>
<emphasis>持久(Persistent)</emphasis> - 持久(Persistent)的实例在数据库中有对应的记录,并拥有一个持久化标识(identifier)。 <emphasis>持久(Persistent)</emphasis> - 持久(Persistent)的实例在数据库中有对应的记录,并拥有一个持久化标识(identifier)。
持久(Persistent)的实例可能是刚被保存的,或刚被加载的,无论哪一种,按定义对象都仅在相关联的<literal>Session</literal>生命周期内的保持这种状态 持久(Persistent)的实例可能是刚被保存的,或刚被加载的,无论哪一种,按定义,它存在于相关联的<literal>Session</literal>作用范围内
Hibernate会检测到处于持久(Persistent)状态的对象的任何改动,在当前操作单元(unit of work)执行完毕时将对象数据(state)与数据库同步(synchronize)。 Hibernate会检测到处于持久(Persistent)状态的对象的任何改动,在当前操作单元(unit of work)执行完毕时将对象数据(state)与数据库同步(synchronize)。
开发者不需要手动执行<literal>UPDATE</literal>。将对象从持久(Persistent)状态变成瞬时(Transient)状态同样也不需要手动执行<literal>DELETE</literal>语句。 开发者不需要手动执行<literal>UPDATE</literal>。将对象从持久(Persistent)状态变成瞬时(Transient)状态同样也不需要手动执行<literal>DELETE</literal>语句。
</para> </para>
@ -46,7 +46,7 @@
<para> <para>
<emphasis>脱管(Detached)</emphasis> - 与持久(Persistent)对象关联的<literal>Session</literal>被关闭后,对象就变为脱管(Detached)的。 <emphasis>脱管(Detached)</emphasis> - 与持久(Persistent)对象关联的<literal>Session</literal>被关闭后,对象就变为脱管(Detached)的。
对脱管(Detached)对象的引用依然有效,对象可继续被修改。脱管(Detached)对象如果重新关联到某个新的<literal>Session</literal>上, 对脱管(Detached)对象的引用依然有效,对象可继续被修改。脱管(Detached)对象如果重新关联到某个新的<literal>Session</literal>上,
会再次转变为持久(Persistent)的(Detached其间的改动将被持久化到数据库)。 会再次转变为持久(Persistent)的(Detached其间的改动将被持久化到数据库)。
这个功能使得一种编程模型,即中间会给用户思考时间(user think-time)的长时间运行的操作单元(unit of work)的编程模型成为可能。 这个功能使得一种编程模型,即中间会给用户思考时间(user think-time)的长时间运行的操作单元(unit of work)的编程模型成为可能。
我们称之为<emphasis>应用程序事务</emphasis>,即从用户观点看是一个操作单元(unit of work)。 我们称之为<emphasis>应用程序事务</emphasis>,即从用户观点看是一个操作单元(unit of work)。
</para> </para>
@ -65,7 +65,7 @@
<para> <para>
Hibernate认为持久化类(persistent class)新实例化的对象是<emphasis>瞬时(Transient)</emphasis>的。 Hibernate认为持久化类(persistent class)新实例化的对象是<emphasis>瞬时(Transient)</emphasis>的。
我们可将瞬时(Transient)对象与session关联而变为<emphasis>持久(Persistent)</emphasis>的。 我们可通过将瞬时(Transient)对象与session关联而把它变为<emphasis>持久(Persistent)</emphasis>的。
</para> </para>
<programlisting><![CDATA[DomesticCat fritz = new DomesticCat(); <programlisting><![CDATA[DomesticCat fritz = new DomesticCat();
@ -100,13 +100,13 @@ sess.save( pk, new Long(1234) );]]></programlisting>
如果你持久化的对象有关联的对象(associated objects)(例如上例中的<literal>kittens</literal>集合) 如果你持久化的对象有关联的对象(associated objects)(例如上例中的<literal>kittens</literal>集合)
那么对这些对象译注pk和kittens进行持久化的顺序是任意的也就是说可以先对kittens进行持久化也可以先对pk进行持久化 那么对这些对象译注pk和kittens进行持久化的顺序是任意的也就是说可以先对kittens进行持久化也可以先对pk进行持久化
除非你在外键列上有<literal>NOT NULL</literal>约束。 除非你在外键列上有<literal>NOT NULL</literal>约束。
Hibernate不会违反外键约束但是如果你用错误的顺序持久化对象译注在pk持久之前持久kitten那么可能会违反<literal>NOT NULL</literal>约束。 Hibernate不会违反外键约束但是如果你用错误的顺序持久化对象译注在pk持久之前持久kitten那么可能会违反<literal>NOT NULL</literal>约束。
</para> </para>
<para> <para>
通常你不会为这些细节烦心因为你很可能会使用Hibernate的 通常你不会为这些细节烦心因为你很可能会使用Hibernate的
<emphasis>传播性持久化(transitive persistence)</emphasis>功能自动保存相关联那些对象。 <emphasis>传播性持久化(transitive persistence)</emphasis>功能自动保存相关联那些对象。
这样连违反<literal>NOT NULL</literal>约束情况都不会出现了 - Hibernate会管好所有的事情。 这样连违反<literal>NOT NULL</literal>约束情况都不会出现了 - Hibernate会管好所有的事情。
传播性持久化(transitive persistence)将在本章稍后讨论。 传播性持久化(transitive persistence)将在本章稍后讨论。
</para> </para>
@ -146,7 +146,7 @@ Set kittens = cat.getKittens();]]></programlisting>
<para> <para>
如果你不确定是否有匹配的行存在,应该使用<literal>get()</literal>方法,它会立刻访问数据库,如果没有对应的会返回null。 如果你不确定是否有匹配的行存在,应该使用<literal>get()</literal>方法,它会立刻访问数据库,如果没有对应的记录会返回null。
</para> </para>
<programlisting><![CDATA[Cat cat = (Cat) sess.get(Cat.class, id); <programlisting><![CDATA[Cat cat = (Cat) sess.get(Cat.class, id);
@ -191,7 +191,7 @@ sess.refresh(cat); //re-read the state (after the trigger executes)]]></programl
<para> <para>
如果不知道所要寻找的对象的持久化标识那么你需要使用查询。Hibernate支持强大且易于使用的面向对象查询语言(HQL)。 如果不知道所要寻找的对象的持久化标识那么你需要使用查询。Hibernate支持强大且易于使用的面向对象查询语言(HQL)。
如果希望通过编程的方式创建查询Hibernate提供了完善的按条件(Query By Criteria, QBC)以及按样例(Query By Example, QBE)进行查询的功能。 如果希望通过编程的方式创建查询Hibernate提供了完善的按条件(Query By Criteria, QBC)以及按样例(Query By Example, QBE)进行查询的功能。
你也可以用原生SQL(native SQL)描述查询Hibernate提供了将结果集(result set)转化为对象的部分支持。 你也可以用原生SQL(native SQL)描述查询Hibernate额外提供了将结果集(result set)转化为对象的支持。
</para> </para>
<sect2 id="objectstate-querying-executing" revision="1"> <sect2 id="objectstate-querying-executing" revision="1">
@ -507,7 +507,7 @@ List cats = crit.list();]]></programlisting>
<para> <para>
你可以使用<literal>createSQLQuery()</literal>方法用SQL来描述查询并由Hibernate处理将结果集转换成对象的工作 你可以使用<literal>createSQLQuery()</literal>方法用SQL来描述查询并由Hibernate将结果集转换成对象。
请注意,你可以在任何时候调用<literal>session.connection()</literal>来获得并使用JDBC <literal>Connection</literal>对象。 请注意,你可以在任何时候调用<literal>session.connection()</literal>来获得并使用JDBC <literal>Connection</literal>对象。
如果你选择使用Hibernate的API, 你必须把SQL别名用大括号包围起来: 如果你选择使用Hibernate的API, 你必须把SQL别名用大括号包围起来:
</para> </para>
@ -577,7 +577,7 @@ sess.flush(); // changes to cat are automatically detected and persisted]]></pr
</para> </para>
<para> <para>
Hibernate通过提供使用<literal>Session.update()</literal><literal>Session.merge()</literal>方法 Hibernate通过提供<literal>Session.update()</literal><literal>Session.merge()</literal>
重新关联脱管实例的办法来支持这种模型。 重新关联脱管实例的办法来支持这种模型。
</para> </para>
@ -608,8 +608,8 @@ secondSession.update(mate); // update mate]]></programlisting>
<para> <para>
希望相关联的脱管对象(通过引用“可到达”的脱管对象)的数据也要更新到数据库时(并且也<emphasis>仅仅</emphasis>在这种情况), 如果希望相关联的脱管对象(通过引用“可到达”的脱管对象)的数据也要更新到数据库时(并且也<emphasis>仅仅</emphasis>在这种情况),
应用程序需要对该相关联的脱管对象单独调用<literal>update()</literal> 可以对该相关联的脱管对象单独调用<literal>update()</literal>
当然这些可以自动完成,即通过使用<emphasis>传播性持久化(transitive persistence)</emphasis>,请看<xref linkend="objectstate-transitive"/> 当然这些可以自动完成,即通过使用<emphasis>传播性持久化(transitive persistence)</emphasis>,请看<xref linkend="objectstate-transitive"/>
</para> </para>
@ -661,7 +661,7 @@ secondSession.saveOrUpdate(mate); // save the new instance (mate has a null id)
<para> <para>
<literal>saveOrUpdate()</literal>用途和语义可能会使新用户感到迷惑。 <literal>saveOrUpdate()</literal>用途和语义可能会使新用户感到迷惑。
首先只要你没有尝试在某个session中使用来自另一session的实例你应该不需要使用<literal>update()</literal> 首先只要你没有尝试在某个session中使用来自另一session的实例应该不需要使用<literal>update()</literal>
<literal>saveOrUpdate()</literal>,或<literal>merge()</literal>。有些程序从来不用这些方法。 <literal>saveOrUpdate()</literal>,或<literal>merge()</literal>。有些程序从来不用这些方法。
</para> </para>
@ -808,7 +808,7 @@ session2.close();]]></programlisting>
<para> <para>
<literal>ReplicationMode</literal>决定数据库中已存在相同行时,<literal>replicate()</literal>如何处理。 <literal>ReplicationMode</literal>决定在和数据库中已存在记录由冲突时,<literal>replicate()</literal>如何处理。
</para> </para>
<itemizedlist spacing="compact"> <itemizedlist spacing="compact">
@ -1072,13 +1072,7 @@ sess.close();]]></programlisting>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
<para> <para>
Finally, note that cascading of operations can be applied to an object graph at 最后,注意操作的级联可能是在<emphasis>调用期(call time)</emphasis>或者<emphasis>写入期(flush time)</emphasis>作用到对象图上的。所有的操作,如果允许,都在操作被执行的时候级联到可触及的关联实体上。然而,<literal>save-upate</literal><literal>delete-orphan</literal>是在<literal>Session</literal> flush的时候才作用到所有可触及的被关联对象上的。
<emphasis>call time</emphasis> or at <emphasis>flush time</emphasis>. All operations,
if enabled, are cascaded to associated entities reachable when the operation is
executed. However, <literal>save-upate</literal> and <literal>delete-orphan</literal>
are transitive for all associated entities reachable during flush of the
<literal>Session</literal>.
最后,注意操作的级联可能是在<emphasis>调用期(call time)</emphasis>或者<emphasis>写入期(flush time)</emphasis>作用到对象图上的。所有的操作,假若允许,都在操作被执行的时候级联到可触及的关联实体上。然而,<literal>save-upate</literal><literal>delete-orphan</literal>是在<literal>Session</literal> flush的时候才作用到所有可触及的被关联对象上的。
</para> </para>

View File

@ -9,11 +9,11 @@
<para> <para>
Hibernate使得你可以用XML数据来进行工作恰如你用持久化的POJO进行工作那样。解析过的XML树 Hibernate使得你可以用XML数据来进行工作恰如你用持久化的POJO进行工作那样。解析过的XML树
可以被认为是另外一种在对象层面上代替POJO来表示关系型数据的途径. 可以被认为是代替POJO的另外一种在对象层面上表示关系型数据的途径.
</para> </para>
<para> <para>
Hibernate支持采用dom4j作为操作XML树的API。你可以写一查询从数据库中检索出 Hibernate支持采用dom4j作为操作XML树的API。你可以写一查询从数据库中检索出
dom4j树随后你对这颗树做的任何修改都将自动同步回数据库。你甚至可以用dom4j解析 dom4j树随后你对这颗树做的任何修改都将自动同步回数据库。你甚至可以用dom4j解析
一篇XML文档然后使用Hibernate的任一基本操作将它写入数据库 一篇XML文档然后使用Hibernate的任一基本操作将它写入数据库
<literal>persist(), saveOrUpdate(), merge(), delete(), replicate()</literal> <literal>persist(), saveOrUpdate(), merge(), delete(), replicate()</literal>
@ -21,7 +21,7 @@
</para> </para>
<para> <para>
这一特性可以应用在很多场合包括数据导入导出通过JMS或SOAP表现实体数据以及 这一特性可以应用在很多场合包括数据导入导出通过JMS或SOAP具体化实体数据以及
基于XSLT的报表。 基于XSLT的报表。
</para> </para>
@ -92,7 +92,7 @@
<para> <para>
这个映射使得你既可以把数据作为一棵dom4j树那样访问又可以作为由属性键值对(java <literal>Map</literal>s) 这个映射使得你既可以把数据作为一棵dom4j树那样访问又可以作为由属性键值对(java <literal>Map</literal>s)
组成的图那样访问。属性名字纯粹逻辑上的结构你可以在HQL查询中引用它。 组成的图那样访问。属性名字纯粹逻辑上的结构你可以在HQL查询中引用它。
</para> </para>
</sect2> </sect2>
@ -262,7 +262,7 @@ tx.commit();
session.close();]]></programlisting> session.close();]]></programlisting>
<para> <para>
将这一特色与Hibernate的<literal>replicate()</literal>操作结合起来实现的基于XML的数据导入/导出将非常有用. 将这一特色与Hibernate的<literal>replicate()</literal>操作结合起来对于实现的基于XML的数据导入/导出将非常有用.
</para> </para>
</sect1> </sect1>