Author: caoxg
Date: 2006-11-07 01:15:35 -0500 (Tue, 07 Nov 2006)
New Revision: 10745
Modified:
trunk/HibernateExt/metadata/doc/reference/zh_cn/master.xml
trunk/HibernateExt/metadata/doc/reference/zh_cn/modules/entity.xml
trunk/HibernateExt/metadata/doc/reference/zh_cn/modules/lucene.xml
trunk/HibernateExt/metadata/doc/reference/zh_cn/modules/setup.xml
trunk/HibernateExt/metadata/doc/reference/zh_cn/modules/validator.xml
trunk/HibernateExt/metadata/doc/reference/zh_cn/modules/xml-overriding.xml
Log:
updated to v3.2.0GA
Modified: trunk/HibernateExt/metadata/doc/reference/zh_cn/master.xml
===================================================================
--- trunk/HibernateExt/metadata/doc/reference/zh_cn/master.xml 2006-11-07 05:58:20 UTC
(rev 10744)
+++ trunk/HibernateExt/metadata/doc/reference/zh_cn/master.xml 2006-11-07 06:15:35 UTC
(rev 10745)
@@ -13,7 +13,7 @@
<subtitle>参考文档</subtitle>
- <releaseinfo>3.2.0 CR1</releaseinfo>
+ <releaseinfo>3.2.0.GA</releaseinfo>
<mediaobject>
<imageobject>
@@ -40,7 +40,10 @@
<sect1 id="preface-translate-comments-zh-cn">
<title>翻译说明</title>
-
<
para>本文档的翻译是在网络上协作进行的,也会不断根据Hibernate的升级进行更新。提供此文档的目的是为了减缓学习Hibernate的...
+ <para>本文档的翻译是在网络上协作进行的,也会不断根据Hibernate的升级进行更新。
+ 提供此文档的目的是为了减缓学习Hibernate的坡度,而非代替原文档。
+ 我们建议所有有能力的读者都直接阅读英文原文。若您对翻译有异议,或发现翻译错误,
+ 敬请不吝赐教,报告到如下地址:http://wiki.redsaga.com/confluence/display/HART/Home</para>
<table frame="topbot" id="redsaga-translate-team">
<title>Hibernate Annotation v3翻译团队</title>
@@ -223,7 +226,11 @@
<term>满江红.开源,
http://www.redsaga.com</term>
<listitem>
-
<
para>从成立之初就致力于Java开放源代码在中国的传播与发展,与国内多个Java团体及出版社有深入交流。坚持少说多做的原则,目前有两个团...
+ <para>从成立之初就致力于Java开放源代码在中国的传播与发展,与国内多个Java团体及出版社有深入交流。
+ 坚持少说多做的原则,目前有两个团队,“OpenDoc团队”与“翻译团队”,本翻译文档即为翻译团队作品。
+ OpenDoc团队已经推出包括Hibernate、iBatis、Spring、WebWork的多份开放文档,
+ 并于2005年5月在Hibernate开放文档基础上扩充成书,出版了原创书籍:《深入浅出Hibernate》,
+
本书400余页,适合各个层次的Hibernate用户。(http://www.redsaga.com/hibernate_book.html)敬请支持。</para>
</listitem>
</varlistentry>
@@ -242,13 +249,16 @@
<sect1 id="preface-translate-licence-zh-cn">
<title>版权声明</title>
-
<para>Hibernate英文文档属于Hibernate发行包的一部分,遵循LGPL协议。本翻译版本同样遵循LGPL协议。参与翻译的译者一致同意放弃除署名权外对本翻译版本的其它权利要求。</para>
+ <para>Hibernate英文文档属于Hibernate发行包的一部分,遵循LGPL协议。本翻译版本同样遵循LGPL协议。
+ 参与翻译的译者一致同意放弃除署名权外对本翻译版本的其它权利要求。</para>
-
<para>您可以自由链接、下载、传播此文档,或者放置在您的网站上,甚至作为产品的一部分发行。但前提是必须保证全文完整转载,包括完整的版权信息和作译者声明,并不能违反LGPL协议。这里“完整”的含义是,不能进行任何删除/增添/注解。若有删除/增添/注解,必须逐段明确声明那些部分并非本文档的一部分。</para>
+ <para>您可以自由链接、下载、传播此文档,或者放置在您的网站上,甚至作为产品的一部分发行。
+ 但前提是必须保证全文完整转载,包括完整的版权信息和作译者声明,并不能违反LGPL协议。
+ 这里“完整”的含义是,不能进行任何删除/增添/注解。若有删除/增添/注解,必须逐段明确声明那些部分并非本文档的一部分。</para>
</sect1>
</preface>
- <preface>
+ <preface id="preface" revision="1">
<title>前言</title>
<para>正如其他的ORM工具,Hibernate同样需要元数据来控制在不同数据表达形式之间的转化. 在Hibernate
@@ -259,7 +269,7 @@
在运行时(对于Hibernate来讲就是启动的时候)通过反射读取这些注解, 因此外部XML文件就不再需要了.</para>
<para>EJB3规范最终认可了透明化ORM的成功范例以及市场对于这种技术的兴趣.
- EJB3规范标准化了ORM的基础API而且在任何ORM持久化机制中使用元数据. <emphasis>Hibernate
+ EJB3规范对ORM的基础API以及在任一ORM持久化机制中所需的元数据进行了标准化. <emphasis>Hibernate
EntityManager</emphasis>实现了EJB3持久化规范中定义的编程接口和生命周期规则.
在<emphasis>Hibernate
Core</emphasis>的基础上再结合 <emphasis>Hibernate
Annotations</emphasis>就实现了一套完整(并且独立)的EJB3持久化解决方案.
@@ -267,12 +277,12 @@
Core</emphasis>. 这些都取决于项目的商业和技术上的实际需求. Hibernate允许你直接使用native APIs,如果有需要,
甚至可以直接操作JDBC和SQL.</para>
- <para>注意本文档基于Hibernate Annotations的预览版(遵从EJB 3.0/JSR-220最终草案).
- 这个版本和新规范中定义的最终概念已经非常接近了.我们的目标是提供一套完整的ORM注解,
- 包括EJB3的标准注解以及Hibernate3的扩展(后者是EJB3规范中没有涉及到的). 最终通过注解你可以完成任何可能的映射.详情参考<xref
- linkend="compliance" />.</para>
+ <para>这个版本基于EJB3.0最终发布版本/JPA规范(也就是JCP-220),该版本支持规范的所有特征
+ (包括可选项)。而Hibernate的那些和规范相比的特征和扩展也可以通过Hibernate的专有注解获得,
+ 虽然该版本的Hibernate特征覆盖程度非常高,不过仍然缺少了一部分,
+ 接下来Hibernate Team的目标就是完全覆盖Hibernate的所有特征。详情参考JIRA的计划图。</para>
- <para>EJB3最终草案修改了部分注解,
+ <para>如果你正在从以前的版本升级到最新的发布版本,
http://www.hibernate.org/371.html提供了从上一个版本到最新版本的迁移指南.</para>
</preface>
@@ -289,6 +299,7 @@
<appendix>
<title id="glossary">术语表</title>
-
<
para>Redsaga的wiki上维护了本文翻译过程中所参照的中英文对照的术语表,地址:http://wiki.redsaga.com/c...
+ <para>Redsaga的wiki上维护了本文翻译过程中所参照的中英文对照的术语表,
+ 地址:http://wiki.redsaga.com/confluence/display/HART/glossary.</para>
</appendix>
</book>
\ No newline at end of file
Modified: trunk/HibernateExt/metadata/doc/reference/zh_cn/modules/entity.xml
===================================================================
--- trunk/HibernateExt/metadata/doc/reference/zh_cn/modules/entity.xml 2006-11-07 05:58:20
UTC (rev 10744)
+++ trunk/HibernateExt/metadata/doc/reference/zh_cn/modules/entity.xml 2006-11-07 06:15:35
UTC (rev 10745)
@@ -5,14 +5,14 @@
<sect1 id="entity-overview" revision="1">
<title>简介</title>
- <para>本章内容覆盖了EJB3.0实体bean的注解规范以及Hibernate特有的扩展.</para>
+ <para>本章内容覆盖了EJB3.0(也就是JPA)实体的注解规范以及Hibernate特有的扩展.</para>
</sect1>
- <sect1 id="mapping" revision="1">
- <title>用EJB3注解进行映射</title>
-
+ <sect1 id="entity-mapping" revision="2">
+ <title>用EJB3/JPA注解进行映射</title>
+
<para>现在EJB3实体Bean是纯粹的POJO.实际上这表达了和Hibernate持久化实体对象同样的概念.
- 它们的映射都通过JDK5.0注解来定义(EJB3规范中的XML描述语法至今还没有最终定下来).
+ 它们的映射都通过JDK5.0注解来定义(EJB3规范已经定义了对应的XML描述语法).
注解分为两个部分,分别是逻辑映射注解和物理映射注解,
通过逻辑映射注解可以描述对象模型,类之间的关系等等,
而物理映射注解则描述了物理的schema,表,列,索引等等.
@@ -45,7 +45,7 @@
<literal>@Id</literal>注解则声明了该实体bean的标识属性.
其他的映射定义是隐式的.这种以隐式映射为主体,以显式映射为例外的配置方式在新的EJ3规范中处于非常重要的位置,
和以前的版本相比有了质的飞跃.
- 在上面这段代码中:Flight类映射到Flight表,并使用id列作为主键列.
+ 在上面这段代码中:Flight类映射到Flight表,并使用id列作为主键列.
</para>
<para>在对一个类进行注解时,你可以选择对它的的属性或者方法进行注解,根据你的选择,Hibernate的访问类型分别为
@@ -60,7 +60,7 @@
<para><literal>@Table</literal>是类一级的注解,
通过<literal>@Table</literal>注解可以为实体bean映射指定表(table),目录(catalog)和schema的名字.
- 如果没有定义<literal>@Table</literal>,那么系统自动使用默认值:实体的短类名(不附带包名).</para>
+ 如果没有定义<literal>@Table</literal>,那么系统自动使用默认值:实体的短类名(不附带包名).</para>
<programlisting>
@Entity
@@ -125,7 +125,7 @@
<para>实体bean中所有的非static非transient的属性都可以被持久化,
除非你将其注解为<literal>@Transient</literal>.所有没有定义注解的属性等价于在其上面添加了(a)xn--basic-w69ki98n.
- 通过 <literal>@Basic</literal>注解可以声明属性的获取策略(fetch strategy):</para>
+ 通过 <literal>@Basic</literal>注解可以声明属性的获取策略(fetch strategy):</para>
<programlisting>public transient int counter; //transient property
@@ -163,7 +163,7 @@
</para>
<note>
- <para>为了启用属性级的延迟获取,你的类必须经过特殊处理(instrumented):
+ <para>为了启用属性级的延迟获取,你的类必须经过特殊处理(instrumented):
字节码将被织入原始类中来实现延迟获取功能,
详情参考Hibernate参考文档.如果不对类文件进行字节码特殊处理,
那么属性级的延迟获取将被忽略.</para>
@@ -217,7 +217,7 @@
<para>使用 <literal>@Column </literal>注解可将属性映射到列.
使用该注解来覆盖默认值(关于默认值请参考EJB3规范).
- 在属性级使用该注解的方式如下:</para>
+ 在属性级使用该注解的方式如下:</para>
<itemizedlist>
<listitem>
@@ -349,7 +349,7 @@
甚至覆盖该实体中原有的列映射.
组件类必须在类一级定义<literal>@Embeddable</literal>注解.
在特定的实体的关联属性上使用<literal>@Embedded</literal>和
- <literal>@AttributeOverride</literal>注解可以覆盖该属性对应的嵌入式对象的列映射:</para>
+ <literal>@AttributeOverride</literal>注解可以覆盖该属性对应的嵌入式对象的列映射:</para>
<programlisting>
@Entity
@@ -421,7 +421,7 @@
这样可以将其父类的属性持久(详情请查阅<literal>(a)MappedSuperclass</literal>).</para>
<para>Hibernate现在支持在嵌入式对象中使用关联注解(如<literal>@*ToOne</literal>和<literal>@*ToMany</literal>).
- 而EJB3规范尚不支持这样的用法。你可以使用
<literal>@AssociationOverride</literal>注解来覆写关联列.</para>
+ 而EJB3规范尚不支持这样的用法.你可以使用
<literal>@AssociationOverride</literal>注解来覆写关联列.</para>
<para>在同一个实体中使用两个同类型的嵌入对象,
@@ -462,7 +462,7 @@
</sect3>
</sect2>
- <sect2 id="mapping-identifier" label=""
+ <sect2 id="entity-mapping-identifier" label=""
xreflabel="Mapping identifier properties">
<title>映射主键属性</title>
@@ -511,11 +511,18 @@
多个<literal>@Id</literal>可以共享同一个identifier生成器,只要把generator属性设成相同的值就可以了.
通过<literal>@SequenceGenerator</literal>
和<literal>@TableGenerator</literal>,你可以配置不同的identifier生成器.
每一个identifier生成器都有自己的适用范围,可以是应用级(application level)和类一级(class level).
- 类一级的生成器在外部是不可见的,
- 而且类一级的生成器可以覆盖应用级的生成器.
- 应用级的生成器则定义在包一级(package
level)(如<classname>package-info.java</classname>):</para>
+ 类一级的生成器在外部是不可见的,而且类一级的生成器可以覆盖应用级的生成器.
+ 应用级的生成器则定义在XML级(请参阅<xref linkend="xml-overriding" />):</para>
- <programlisting>
+ <programlisting><table-generator name="EMP_GEN"
+ table="GENERATOR_TABLE"
+ pk-column-name="key"
+ value-column-name="hi"
+ pk-column-value="EMP"
+ allocation-size="20"/>
+
+//and the annotation equivalent
+
@javax.persistence.TableGenerator(
name="EMP_GEN",
table="GENERATOR_TABLE",
@@ -524,16 +531,22 @@
pkColumnValue="EMP",
allocationSize=20
)
+
+<sequence-generator name="SEQ_GEN"
+ sequence-name="my_sequence"
+ allocation-size="20"/>
+
+//and the annotation equivalent
+
@javax.persistence.SequenceGenerator(
name="SEQ_GEN",
- sequenceName="my_sequence"
+ sequenceName="my_sequence",
+ allocationSize=20
)
-package org.hibernate.test.metadata;
</programlisting>
-
+
<para>
- 如果在<classname>org.hibernate.test.metadata</classname>包下面的
- <classname>package-info.java</classname>文件用于初始化EJB配置,
+ 如果JPA XML(如<filename>META-INF/orm.xml</filename>)用于定义生成器,
那么该文件中定义的 <literal>EMP_GEN</literal>
和<literal>SEQ_GEN</literal>都是应用级的生成器.
<literal>EMP_GEN</literal>定义了一个使用hilo算法
@@ -544,6 +557,19 @@
而<literal>valueColumnName</literal>
"<literal>hi</literal>"中存储的是下一个要使用的最大值.
</para>
+ <para><literal>SEQ_GEN</literal>定义了一个sequence生成器,
+ 其使用名为<literal>my_sequence</literal>的sequence.
+ 该hilo算法基于sequence,该sequence分配的大小为20.
+ 注意,现在这个版本还不能处理sequence生成器的<literal>initialValue</literal>属性.
+ 默认分配的大小为50,因此如果你打算使用sequence,并且希望每次都重新获取新的值,务必将
+ 分配的大小设置为1.</para>
+
+ <note>
+ <para>EJB3.0规范已经不再支持Package级别的定义. 但是你仍然可以在包上使用
+ <literal>@GenericGenerator</literal>注解(详情请参考<xref
+ linkend="entity-hibspec-identifier" />).</para>
+ </note>
+
<para><literal>SEQ_GEN</literal>则定义了一个sequence 生成器,
其对应的sequence名为 <literal>my_sequence</literal>.
注意目前Hibernate Annotations还不支持sequence 生成器中的
@@ -747,7 +773,7 @@
<literal>InheritanceType.SINGLE_TABLE</literal>,并通过
<literal>@DiscriminatorColumn</literal>注解定义了辨别符列(还可以定义辨别符的类型).
最后,对于继承层次结构中的每个类,<literal>@DiscriminatorValue</literal>注解指定了用来辨别该类的值.
- 辨别符列的名字默认为
<literal>DTYPE</literal>,其默认值为实体名(在<literal>(a)Entity.xn--name</literal>),-4m78ahth94dwj1bn5wzn4s
+ 辨别符列的名字默认为
<literal>DTYPE</literal>,其默认值为实体名(在<literal>(a)Entity.xn--name</literal>),-4m78ahth94dwj1bn5wzn4s
为DiscriminatorType.STRING.
<classname>A320</classname>是子类,如果不想使用默认的辨别符,只需要指定相应的值即可.
其他的如继承策略,辨别标志字段的类型都是自动设定的.</para>
@@ -887,7 +913,7 @@
<title>一对一(One-to-one)</title>
<para>使用<literal>@OneToOne</literal>注解可以建立实体bean之间的一对一的关联.
- 一对一关联有三种情况:
+ 一对一关联有三种情况:
一是关联的实体都共享同样的主键,
二是其中一个实体通过外键关联到另一个实体的主键
(注意要模拟一对一关联必须在外键列上添加唯一约束).
@@ -952,15 +978,15 @@
</para>
<para>一对一关联可能是双向的.在双向关联中,
- 有且仅有一端是作为主体(owner)端存在的:主体端负责维护联接列(即更新).
+ 有且仅有一端是作为主体(owner)端存在的:主体端负责维护联接列(即更新).
对于不需要维护这种关系的从表则通过mappedBy属性进行声明.
<literal>mappedBy</literal>的值指向主体的关联属性.
在上面这个例子中,<literal>mappedBy</literal>的值为
<literal>passport</literal>.
最后,不必也不能再在被关联端(owned side)定义联接列了,因为已经在主体端进行了声明.</para>
- <para>如果在主体没有声明<literal>@JoinColumn</literal>,系统自动进行处理:
+ <para>如果在主体没有声明<literal>@JoinColumn</literal>,系统自动进行处理:
在主表(owner table)中将创建联接列,
- 列名为:主体的关联属性名+下划线+被关联端的主键列名.
+ 列名为:主体的关联属性名+下划线+被关联端的主键列名.
在上面这个例子中是<literal>passport_id</literal>,
因为<literal>Customer</literal>中关联属性名为<literal>passport</literal>,
<literal>Passport</literal>的主键是<literal>id</literal>.</para>
@@ -996,13 +1022,6 @@
而<literal>customer_fk</literal>外键列指向<literal>Customer</literal>表,
该信息定义为 <literal>joinColumns</literal>的属性值.</para>
- <para>这种关联可能是双向的.在双向关联中,
- 有且仅有一端是作为主体端存在的:主体端负责维护联接列(即更新).
- 对于不需要维护这种关系的从表则通过mappedBy属性进行声明.
- <literal>mappedBy</literal>的值指向主体的关联属性.
- 在上面这个例子中,<literal>mappedBy</literal>的值为
<literal>passport</literal>.
- 最后,不必也不能再在被关联端(owned side)定义联接列了,因为已经在主体端进行了声明.</para>
-
<para>你必须明确定义关联表名和关联列名.</para>
</sect3>
@@ -1026,7 +1045,7 @@
<para>其中<literal>@JoinColumn</literal>是可选的,关联字段默认值和一对一
(one to one)关联的情况相似,
- 列名为:主体的关联属性名+下划线+被关联端的主键列名.
+ 列名为:主体的关联属性名+下划线+被关联端的主键列名.
在这个例子中是<literal>company_id</literal>,
因为关联的属性是<literal>company</literal>,
<literal>Company</literal>的主键是<literal>id</literal>.</para>
@@ -1034,7 +1053,7 @@
<para><literal>@ManyToOne</literal>注解有一个名为<literal>targetEntity</literal>的参数,
该参数定义了目标实体名.通常不需要定义该参数,
因为在大部分情况下默认值(表示关联关系的属性类型)就可以很好的满足要求了.
- 不过下面这种情况下这个参数就显得有意义了:使用接口作为返回值而不是常见的实体.</para>
+ 不过下面这种情况下这个参数就显得有意义了:使用接口作为返回值而不是常见的实体.</para>
<programlisting>
@Entity()
@@ -1052,8 +1071,8 @@
...
</programlisting>
- <para>对于多对一也可以通过关联表的方式来映射。
- 通过<literal>@JoinTable</literal>注解可定义关联表,
+ <para>对于多对一也可以通过关联表的方式来映射.
+ 通过<literal>@JoinTable</literal>注解可定义关联表,
该关联表包含了指回实体表的外键(通过<literal>(a)JoinTable.joinColumns</literal>)
以及指向目标实体表的外键(通过<literal>(a)JoinTable.inverseJoinColumns</literal>).</para>
@@ -1076,15 +1095,16 @@
<sect3 id="entity-mapping-association-collections">
<title>集合类型</title>
- <sect4>
+ <sect4 id="entity-mapping-association-collections-overview"
+ revision="1">
<title>概况</title>
<para>你可以对 <classname>Collection
</classname>,<literal>List</literal>
(指有序列表, 而不是索引列表),
<literal>Map</literal>和<classname>Set</classname>这几种类型进行映射.
EJB3规范定义了怎么样使用<literal>(a)javax.persistence.OrderBy</literal>
- 注解来对有序列表进行映射:
- 该注解接受的参数格式:用逗号隔开的(目标实体)属性名及排序指令,
+ 注解来对有序列表进行映射:
+ 该注解接受的参数格式:用逗号隔开的(目标实体)属性名及排序指令,
如<code>firstname asc, age desc</code>,如果该参数为空,则默认以id对该集合进行排序.
如果某个集合在数据库中对应一个关联表(association table)的话,你不能在这个集合属性上面使用@OrderBy注解.
对于这种情况的处理方法,请参考<xref linkend="entity-hibspec" />.
@@ -1092,13 +1112,13 @@
这个属性可以用<literal>@MapKey(name="myProperty")</literal>来声明.
如果使用<literal>@MapKey</literal>注解的时候不提供属性名,
系统默认使用目标实体的主键.
- map的key使用和属性相同的列:不需要为map key定义专用的列,因为map key实际上就表达了一个目标属性。
+ map的key使用和属性相同的列:不需要为map key定义专用的列,因为map key实际上就表达了一个目标属性.
注意一旦加载,key不再和属性保持同步,
也就是说,如果你改变了该属性的值,在你的Java模型中的key不会自动更新
(请参考<xref linkend="entity-hibspec" />).
-
很多人被<literal><map></literal>和<literal>@MapKey</literal>弄糊涂了。
+
很多人被<literal><map></literal>和<literal>@MapKey</literal>弄糊涂了.
其他它们有两点区别.<literal>@MapKey</literal>目前还有一些限制,详情请查看论坛或者
- 我们的JIRA缺陷系统。
+ 我们的JIRA缺陷系统.
注意一旦加载,key不再和属性保持同步,
@@ -1138,7 +1158,16 @@
<entry>(a)org.hibernate.annotations.CollectionOfElements 或
@OneToMany 或 @ManyToMany</entry>
</row>
+
+ <row>
+ <entry>带主键的Bag语义(没有普通Bag语义的限制)</entry>
+ <entry>java.util.List, java.util.Collection</entry>
+
+ <entry>((a)org.hibernate.annotations.CollectionOfElements 或
+ @OneToMany 或 @ManyToMany) 和 @CollectionId</entry>
+ </row>
+
<row>
<entry>List 语义</entry>
@@ -1166,13 +1195,8 @@
<entry>((a)org.hibernate.annotations.CollectionOfElements 或
@OneToMany 或 @ManyToMany)
- 以及
- (空
- 或
- @org.hibernate.annotations.MapKey/MapKeyManyToMany(支持真正的map),
- 或
- @javax.persistence.MapKey</entry>
-
+ 以及(空或(a)org.hibernate.annotations.xn--mapkey/mapkeymanytomany(map)-1801dj24atl9b2o0edge,
+ 或(a)javax.persistence.MapKey</entry>
</row>
</tbody>
</tgroup>
@@ -1351,13 +1375,14 @@
(<literal>inversejoinColumns</literal>).</para>
</sect5>
- <sect5>
+ <sect5
id="entity-mapping-association-collection-manytomany-default"
+ revision="1">
<title>默认处理机制</title>
<para>通过联接表来建立单向一对多关联不需要描述任何物理映射.
表名由以下三个部分组成:主表(owner table)表名+下划线+从表(the other side table)表名.
- 指向主表的外键名:主表表名+下划线+主表主键列名
- 指向从表的外键名:主表所对应实体的属性名+下划线+从表主键列名
+ 指向主表的外键名:主表表名+下划线+主表主键列名
+ 指向从表的外键名:主表所对应实体的属性名+下划线+从表主键列名
指向从表的外键定义为唯一约束,用来表示一对多的关联关系.</para>
<programlisting>
@@ -1384,7 +1409,8 @@
</sect5>
</sect4>
- <sect4>
+ <sect4 id="eentity-mapping-association-collection-manytomany"
+ revision="">
<title>多对多(Many-to-many)</title>
<sect5>
@@ -1462,7 +1488,7 @@
}
</programlisting>
- <para>上面这个例子中,<literal>Store_Table</literal>作为联接表.
+ <para>上面这个例子中,<literal>Store_City</literal>作为联接表.
<literal>Store_id</literal>列是联接到<literal>Store</literal>表的外键.
而<literal>implantedIn_id</literal>列则联接到<literal>City</literal>表.</para>
@@ -1492,7 +1518,7 @@
<para>在上面这个例子中,<literal>Store_Customer</literal>作为联接表.
<literal>stores_id</literal>列是联接到<literal>Store</literal>表的外键,
- 而<literal>customers_id</literal>列联接到<literal>City</literal>表.</para>
+ 而<literal>customers_id</literal>列联接到<literal>Customer</literal>表.</para>
</sect5>
</sect4>
@@ -1551,7 +1577,7 @@
和<literal>@Embeddable</literal>两个注解.
还有一种方式是使用<literal>(a)xn--embeddedid</literal>-py52dh538a.xn--xsq950adkdxpbu4bv75amglopfxrp264b0vza
serializable以及实现<methodname>equals()</methodname>/<methodname>hashCode()</methodname>方法.
- 你也可以如<xref linkend="mapping-identifier"
/>一章中描述的办法使用<literal>(a)xn--idclass</literal>-vz75ck856a.</para>
+ 你也可以如<xref linkend="entity-mapping-identifier"
/>一章中描述的办法使用<literal>(a)xn--idclass</literal>-vz75ck856a.</para>
<programlisting>
@Entity
@@ -1690,22 +1716,24 @@
<sect1 id="entity-mapping-query">
<title>映射查询</title>
- <sect2>
- <title>映射EJBQL/HQL查询</title>
+ <sect2 id="entity-mapping-query-hql" label="Mapping JPAQL/HQL
queries"
+ revision="1">
+ <title>映射JPAQL/HQL查询</title>
<para>使用注解还可以映射EJBQL/HQL查询.
- <literal>@NamedQuery</literal>
和<literal>@NamedQueries</literal>是可使用在类和包上的注解.
+ <literal>@NamedQuery</literal>
和<literal>@NamedQueries</literal>注解可使用在类和JPA XML文件中.
但是它们的定义在session factory/entity manager factory范围中是都可见的.
命名式查询通过它的名字和实际的查询字符串来定义.</para>
- <programlisting>
-javax.persistence.NamedQueries(
- @javax.persistence.NamedQuery(name="plane.getAll", query="select p
from Plane p")
-)
-package org.hibernate.test.annotations.query;
-
+ <programlisting><entity-mappings>
+ <named-query name="plane.getAll">
+ <query>select p from Plane p</query>
+ </named-query>
+ ...
+</entity-mappings>
...
+
@Entity
@NamedQuery(name="night.moreRecentThan", query="select n from Night n
where n.date >= :date")
public class Night {
@@ -1726,7 +1754,7 @@
<para>还可以通过定义 <literal>QueryHint</literal>
数组的<literal>hints</literal>
属性为查询提供一些hint信息.</para>
- <para>下面是目前可以使用的一些Hibernate hint:</para>
+ <para>下面是目前可以使用的一些Hibernate hint:</para>
<para></para>
@@ -1806,10 +1834,13 @@
<para>你还可以映射本地化查询(也就是普通SQL查询).
不过这需要你使用<literal>@SqlResultSetMapping</literal>注解来描述SQL的resultset的结构
- (如果你打算定义多个结果集映射,可是使用<literal>@SqlResultSetMappings</literal>).
+ (如果你打算定义多个结果集映射,可是使用<literal>@SqlResultSetMappings</literal>).
<literal>@SqlResultSetMapping</literal>和<literal>@NamedQuery</literal>,
- <literal>@SqlResultSetMapping</literal>一样,可以定义在类和包一级.
+ <literal>@SqlResultSetMapping</literal>一样,可以定义在类和JPA XML文件中.
但是<literal>@SqlResultSetMapping</literal>的作用域为应用级.
+ </para>
+
+ <para>
下面我们会看到,<literal>@NamedNativeQuery</literal> 注解中
<literal>resultSetMapping</literal>参数值为<literal>@SqlResultSetMapping</literal>的名字.
结果集映射定义了通过本地化查询返回值和实体的映射.
@@ -1883,7 +1914,7 @@
在这个例子中,<literal>model</literal>属性绑定到<literal>model_txt</literal>列.
如果和相关实体的关联设计到组合主键,
那么应该使用<literal>@FieldResult</literal>注解来定义每个外键列.
- <literal>@FieldResult</literal>的名字由以下几部分组成:
+ <literal>@FieldResult</literal>的名字由以下几部分组成:
定义这种关系的属性名字+"."+主键名或主键列或主键属性.</para>
<programlisting>@Entity
@@ -2007,7 +2038,7 @@
<programlisting><emphasis
role="bold">@SqlResultSetMapping(name="scalar",
columns=@ColumnResult(name="dimension"))
@NamedNativeQuery(name="scalar", query="select length*width as dimension
from SpaceShip",
resultSetMapping="scalar")</emphasis></programlisting>
- <para>本地查询中还有另外一个hint属性:
+ <para>本地查询中还有另外一个hint属性:
<literal>org.hibernate.callable</literal>.
这个属性的布尔变量值表明这个查询是否是一个存储过程.</para>
</sect2>
@@ -2070,10 +2101,10 @@
</note>
</para>
- <para>以下是一些附加的Hibernate注解扩展:</para>
+ <para>以下是一些附加的Hibernate注解扩展:</para>
<para><literal>(a)org.hibernate.annotations.BatchSize</literal>
- 允许你定义批量获取该实体的实例数量(如:<literal>@BatchSize(size=4)</literal>).
+ 允许你定义批量获取该实体的实例数量(如:<literal>@BatchSize(size=4)</literal>).
当加载一特定的实体时,Hibernate将加载在持久上下文中未经初始化的同类型实体,直至批量数量(上限).</para>
<para><literal>(a)org.hibernate.annotations.Proxy</literal>
@@ -2087,7 +2118,7 @@
定义了在DDL语句中定义的合法性检查约束(该约束为可选).</para>
<para><literal>(a)OnDelete(action=OnDeleteAction.CASCADE)</literal>
- 定义于被连接的子类(joined subclass):在删除时使用SQL级连删除,而非通常的Hibernate删除机制.</para>
+ 定义于被连接的子类(joined subclass):在删除时使用SQL级连删除,而非通常的Hibernate删除机制.</para>
<para><literal>@Table(name="tableName", indexes = {
@Index(name="index1", columnNames={"column1",
"column2"} ) } )</literal>
@@ -2102,7 +2133,7 @@
<para>
<literal>(a)org.hibernate.annotations.Table</literal> 是对
<literal>@javax.persistence.Table</literal>的补充而不是它的替代品.
- 特别是当你打算改变表名的默认值的时候,你必须使用<literal>(a)javax.persistence.Table</literal>,
+ 特别是当你打算改变表名的默认值的时候,你必须使用<literal>(a)javax.persistence.Table</literal>,
而不是<literal>(a)org.hibernate.annotations.Table</literal>.</para>
</note>
@@ -2126,7 +2157,7 @@
public class Carrot extends Vegetable { ... }</programlisting></para>
</sect2>
- <sect2>
+ <sect2 id="entity-hibspec-identifier" label="Identifier"
revision="1">
<title>标识符</title>
<para><literal><literal>(a)org.hibernate.annotations.GenericGenerator</literal>
@@ -2148,9 +2179,20 @@
<para><literal>strategy</literal>可以是Hibernate3生成器策略的简称,
或者是一个<classname>IdentifierGenerator</classname>实现的(带包路径的)全限定类名.
你可以通过<literal>parameters</literal>属性增加一些参数.</para>
-</sect2>
+
+ <para>和标准的对比,<literal>@GenericGenerator</literal>是可用于包一级的注解,
+ 使之成为应用级的生成器(就象在JPA XML文件里面那样).</para>
-<sect2 id="entity-hibspec-property" revision="2">
+ <programlisting>@GenericGenerator(name="hibseq", strategy =
"seqhilo",
+ parameters = {
+ @Parameter(name="max_lo", value = "5"),
+ @Parameter(name="sequence", value="heybabyhey")
+ }
+)
+package org.hibernate.test.model</programlisting>
+ </sect2>
+
+ <sect2 id="entity-hibspec-property" revision="2">
<title>属性</title>
<sect3>
@@ -2160,7 +2202,7 @@
在实体继承层次中所处的位置推演而得的.子实体(Sub-entities),
内嵌对象和被映射的父类均继承了根实体(root entity)的访问类型.</para>
- <para>在Hibernate中,你可以把访问类型覆盖成:</para>
+ <para>在Hibernate中,你可以把访问类型覆盖成:</para>
<itemizedlist>
<listitem>
@@ -2172,7 +2214,7 @@
</listitem>
</itemizedlist>
- <para>为支持这种行为,Hibernate引入了(a)xn--accesstype-mh3wx75w.xn--:</para>-o40ug2aj5ea62tkwp00ntosb7ul4bx096a1mdu49jeqvc;
+ <para>为支持这种行为,Hibernate引入了@AccessType注解.你可以对以下元素定义访问类型:</para>
<itemizedlist>
<listitem>
@@ -2198,12 +2240,12 @@
<para>若访问类型被标以"property",则Hibernate会扫描getter方法的注解,若访问类型被标以"field",
则扫描字段的注解.否则,扫描标为@Id或(a)xn--embeddedid-fx9pl096ar7ra.</para>
- <para>你可以覆盖某个属性(property)的访问类型,但是受注解的元素将不受影响:
+ <para>你可以覆盖某个属性(property)的访问类型,但是受注解的元素将不受影响:
例如一个具有field访问类型的实体,(我们)可以将某个字段标注为 @AccessType("property"),
则该字段的访问类型随之将成为property,但是其他字段上依然需要携带注解.</para>
<para>若父类或可内嵌的对象没有被注解,则使用根实体的访问类型(即使已经在非直系父类或可内嵌对象上定义了访问类型).
- 此时俄罗斯套娃(Russian doll)原理就不再适用.(译注:俄罗斯套娃(матрёшка或 матрешка)是俄罗斯特产木制玩具,
+ 此时俄罗斯套娃(Russian doll)原理就不再适用.(译注:俄罗斯套娃(матрёшка或 матрешка)是俄罗斯特产木制玩具,
一般由多个一样图案的空心木娃娃一个套一个组成,最多可达十多个,通常为圆柱形,底部平坦可以直立.)</para>
<programlisting>@Entity
@@ -2262,7 +2304,7 @@
<title>类型</title>
<para><literal>(a)org.hibernate.annotations.Type</literal>
- 覆盖了Hibernate所用的默认类型:这通常不是必须的,因为类型可以由Hibernate正确推得.
+ 覆盖了Hibernate所用的默认类型:这通常不是必须的,因为类型可以由Hibernate正确推得.
关于Hibernate类型的详细信息,请参考Hibernate使用手册.</para>
<para><literal>(a)org.hibernate.annotations.TypeDef</literal> 和
@@ -2375,21 +2417,27 @@
</sect2>
- <sect2>
+ <sect2 id="entity-hibspec-inheritance" revision="1">
<title>继承</title>
<para>SINGLE_TABLE 是个功能强大的策略,但有时,特别对遗留系统而言,
是无法加入一个额外的辨别符列.
- 由此,Hibernate引入了辨别符公式(discriminator formula)的概念:
+ 由此,Hibernate引入了辨别符公式(discriminator formula)的概念:
<literal>@DiscriminatorFormula</literal>是<literal>@DiscriminatorColumn</literal>的替代品,
它使用SQL片段作为辨别符解决方案的公式( 不需要有一个专门的字段).</para>
<programlisting>@Entity
@DiscriminatorForumla("case when forest_type is null then 0 else forest_type
end")
public class Forest { ... }</programlisting>
+
+ <para>默认情况下查询顶级实体,Hibernate不会加入带鉴别器列的约束条件子句.
+ 但是如果该列中还包含了和继承层次无关的值(通过<literal>@DiscriminatorValue</literal>)
+ 就会很不方便.为了解决这个问题,你可以在类上使用<literal>@ForceDiscriminator</literal>注解
+ (将该注解放在<literal>@DiscriminatorColumn</literal>后面).
+ 这样Hibernate在加载实体的时候就可以列出对应的值.</para>
</sect2>
- <sect2>
+ <sect2 id="entity-hibspec-singleassoc">
<title>关于单个关联关系的注解</title>
<para>默认情况下,当预期的被关联元素不在数据库中(关乎关联列的错误id),致使Hiberante无法解决关联性问题时,Hibernate就会抛出异常.
@@ -2421,6 +2469,20 @@
<para>上面这个例子中,Hibernate将生成一个数据库级的级联删除约束.</para>
+ <para>Hibernate生成的外键约束的名字可读性相当差,
+ 你可以使用<literal>@ForeignKey</literal>注解覆盖自动生成的值.</para>
+
+ <programlisting>@Entity
+public class Child {
+ ...
+ @ManyToOne
+ <emphasis
role="bold">@ForeignKey(name="FK_PARENT")</emphasis>
+ public Parent getParent() { ... }
+ ...
+}
+
+alter table Child add constraint FK_PARENT foreign key (parent_id) references
Parent</programlisting>
+
<sect3>
<title>延迟选项和获取模式</title>
@@ -2523,8 +2585,8 @@
<sect2 id="entity-hibspec-collection" revision="2">
<title>关于集合类型的注解</title>
- <sect3>
- <title>参数注解</title>
+ <sect3 id="entity-hibspec-collection-enhance"
revision="2">
+ <title>增强集合设置</title>
<para>以下是可能的设置方式<itemizedlist>
<listitem>
@@ -2532,7 +2594,8 @@
</listitem>
<listitem>
- 用@Where注解设置Where子句
+ 用@Where或@WhereJoinTable注解设置Where子句,
+ 这两种注解分别应用于目标实体和关联表
</listitem>
<listitem>
@@ -2550,7 +2613,9 @@
<para>你也可以利用<literal>@Sort</literal>注解定义一个排序比较器(sort
comparator),
表明希望的比较器类型,无序、自然顺序或自定义排序,三者择一.若你想用你自己实现的comparator,
- 你还需要利用<literal>comparator</literal>属性(attribute)指明实现类.</para>
+ 你还需要利用<literal>comparator</literal>属性(attribute)指明实现类.
+ 注意你需要使用<classname>SortedSet</classname>或<classname>SortedMap</classname>接口
+ </para>
<programlisting> @OneToMany(cascade=CascadeType.ALL,
fetch=FetchType.EAGER)
@JoinColumn(name="CUST_ID")
@@ -2562,42 +2627,158 @@
}</programlisting>
<para>关于这些注解更详细的信息,请参阅此前的描述.</para>
+
+ <para>Hibernate生成的外键约束的名字可读性相当差,
+ 你可以使用<literal>@ForeignKey</literal>注解覆盖自动生成的值.
+ 注意该注解应该置于关联关系的主体端,<literal>inverseName</literal>
+ 指向另一端的约束.
+ </para>
+ <programlisting>@Entity
+public class Woman {
+ ...
+ @ManyToMany(cascade = {CascadeType.ALL})
+ <emphasis role="bold">@ForeignKey(name = "TO_WOMAN_FK",
inverseName = "TO_MAN_FK")</emphasis>
+ public Set<Man> getMens() {
+ return mens;
+ }
+}
+
+alter table Man_Woman add constraint TO_WOMAN_FK foreign key (woman_id) references Woman
+alter table Man_Woman add constraint TO_MAN_FK foreign key (man_id) references Man
+ </programlisting>
+
</sect3>
- <sect3>
+ <sect3 id="entity-hibspec-collection-extratype"
revision="1">
<title>更多的集合类型</title>
+
+ <sect4>
+ <title>List</title>
- <para>比EJB3更胜一筹的是,Hibernate Annotations支持真正的
+ <para>比EJB3更胜一筹的是,Hibernate Annotations支持真正的
<classname>List</classname>和<classname>Array</classname>.
映射集合的方式和以前完全一样,只不过要新增<literal>@IndexColumn</literal>注解.
该注解允许你指明存放索引值的字段.你还可以定义代表数据库中首个元素的索引值(亦称为索引基数).
常见取值为<literal>0</literal>或<literal>1</literal>.</para>
- <programlisting>@OneToMany(cascade = CascadeType.ALL)
+ <programlisting>@OneToMany(cascade = CascadeType.ALL)
@IndexColumn(name = "drawer_position", base=1)
public List<Drawer> getDrawers() {
return drawers;
}</programlisting>
- <note>
- <para>假如你忘了设置<literal>@IndexColumn</literal>,
- Hibernate会采用包(bag)语义(译注:即允许重复元素的无序集合).</para>
- </note>
+ <note>
+ <para>假如你忘了设置<literal>@IndexColumn</literal>,
+ Hibernate会采用bag语义(译注:即允许重复元素的无序集合).
+ 如果你既想使用bag语义,但是又不希望受制于其约束语义,
+ 可以考虑使用<literal>@CollectionId</literal>注解.
+ </para>
+ </note>
+ </sect4>
- <para>Hibernate注解支持true Map映射,
- 如果没有设置<literal>(a)javax.persistence.MapKey</literal>,
- hibernate将key元素或嵌入式对象直接映射到他们所属的列.
- 要覆写默认的列,可以使用以下注解:
- <literal>@org.hibernate.annotations.MapKey</literal>适用的key为基本类型或者嵌入式对象,
- <literal>(a)org.hibernate.annotations.xn--mapkey</literal>key-dm63b1yquv0hc19hksiem0s.
- </para>
+ <sect4>
+ <title>Map</title>
+
+ <para>Hibernate注解支持true Map映射,
+ 如果没有设置<literal>(a)javax.persistence.MapKey</literal>,
+ hibernate将key元素或嵌入式对象直接映射到他们所属的列.
+ 要覆写默认的列,可以使用以下注解:
+ <literal>(a)org.hibernate.annotations.xn--mapkey</literal>key-dm63b415m1scf52oox4di2ik71cdx0j
+ (默认为<literal>mapkey</literal>)或者嵌入式对象,
+ <literal>(a)org.hibernate.annotations.xn--mapkey</literal>key-dm63b1yquv0hc19hksiem0s.
+ </para>
+ </sect4>
+
+ <sect4 id="entity-hibspec-collection-extratype-indexbidir">
+ <title>带索引集合的双向关联</title>
+
+ <para>双向关联的其中一端在使用<literal>@IndexColumn</literal>或者
+ <literal>(a)org.hibernate.annotations.xn--mapkey[manytomany]</literal>-8660f8863b
+ 需要考虑一些特殊的因素.如果子类存在某个属性映射到索引列,这种情况下是没有问题的,我们可以
+ 继续在集合映射的时候使用<literal>mappedBy</literal>,如下:</para>
+
+ <programlisting>@Entity
+public class Parent {
+ @OneToMany(mappedBy="parent")
+ @org.hibernate.annotations.MapKey(columns=@Column(name="name"))
+ private Map<String, Child> children;
+ ...
+}
+
+@Entity
+public class Parent {
+ ...
+ @Basic
+ private String name;
+
+ @ManyToOne
+ @JoinColumn(name="parent_id", nullable=false)
+ private Parent parent;
+ ...
+}</programlisting>
+
+ <para>但是,如果在子类中没有该属性,我们就不能认为这种关联是真正的双向关联
+ (也就是在关联的一端有信息而另一端没有).因此在这种情况下,我们就不能使用
+ <literal>mappedBy</literal>将其映射集合.取而代之为下面这种映射方式:</para>
+
+ <programlisting>@Entity
+public class Parent {
+ @OneToMany
+ @org.hibernate.annotations.MapKey(columns=@Column(name="name"))
+ @JoinColumn(name="parent_id", nullable=false)
+ private Map<String, Child> children;
+ ...
+}
+
+@Entity
+public class Parent {
+ ...
+ @ManyToOne
+ @JoinColumn(name="parent_id", insertable=false, updatable=false,
nullable=false)
+ private Parent parent;
+ ...
+}</programlisting>
+
+ <para>注意在上面的映射中,关联的集合端负责更新外键.</para>
+ </sect4>
+
+ <sect4>
+ <title>带主键的包</title>
+
+ <para>另外一个有趣的特征就是可以给bag集合定义一个代理主键.通过这种方式
+ 优雅的去除了bag的缺点:update和remove操作更加有效率,每次查询或每个实体可以
+ 超过一个<literal>EAGER</literal> bag.该主键被保存在集合表的一个附加列,
+ 该列对于Java应用不可见.@CollectionId注解将一个集合标注为id bag,同时还
+ 可以覆写主键列,主键类型以及生成器策略.生成器策略可以是<literal>identity</literal>,
+ 也可以是应用中任何已定义的生成器的名字.</para>
+
+ <programlisting>@Entity
+@TableGenerator(name="ids_generator", table="IDS")
+public class Passport {
+ ...
+
+ @ManyToMany(cascade = CascadeType.ALL)
+ @JoinTable(name="PASSPORT_VISASTAMP")
+ <emphasis role="bold">@CollectionId(
+ columns = @Column(name="COLLECTION_ID"),
+ type=@Type(type="long"),
+ generator = "ids_generator"
+ )</emphasis>
+ private Collection<Stamp> visaStamp = new ArrayList();
+ ...
+}</programlisting>
+ </sect4>
+
+ <sect4>
+ <title>元素或组合元素的集合</title>
+
<para>Hibernate Annotations还支持核心类型集合(Integer, String, Enums, ......)、
可内嵌对象的集合,甚至基本类型数组.这就是所谓的元素集合.</para>
<para>元素集合可用@CollectionOfElements来注解(作为@OneToMany的替代).
- 为了定义集合表(译注:即存放集合元素的表,与下面提到的主表对应),要在关联属性上使用@JoinTable注解,
+ 为了定义集合表(译注:即存放集合元素的表,与下面提到的主表对应),要在关联属性上使用@JoinTable注解,
joinColumns定义了介乎实体主表与集合表之间的连接字段(inverseJoincolumn是无效的且其值应为空).
对于核心类型的集合或基本类型数组,你可以在关联属性上用<literal>@Column</literal>来覆盖存放元素值的字段的定义.
你还可以用<literal>@AttributeOverride</literal>来覆盖存放可内嵌对象的字段的定义.
@@ -2718,6 +2899,7 @@
用<literal>@OneToMany</literal>来标识集合元素的这种旧有方式目前尚有效,
但是不推荐使用,而且在以后的发布版本中不再支持这种方式.</para>
</note>
+ </sect4>
</sect3>
</sect2>
@@ -2764,11 +2946,11 @@
</callout>
<callout arearefs="hm2">
- <para>region (可选的):缓存范围(默认为类的全限定类名或是集合的全限定角色名)</para>
+ <para>region (可选的):缓存范围(默认为类的全限定类名或是集合的全限定角色名)</para>
</callout>
<callout arearefs="hm3">
- <para><literal>include</literal>
(可选的):值为all时包括了所有的属性(proterty),
+ <para><literal>include</literal>
(可选的):值为all时包括了所有的属性(proterty),
为non-lazy时仅含非延迟属性(默认值为all)</para>
</callout>
</calloutlist>
@@ -2776,16 +2958,17 @@
</programlistingco>
</sect2>
- <sect2>
+ <sect2 id="entity-hibspec-filters">
<title>过滤器</title>
- <para>Hibernate具有数据过滤器的概念,可在运行期应用于一个给定的session.过滤器需要事先定义好.</para>
+
<para>Hibernate具有在数据上应用任意过滤器的能力,可在运行期应用于一个给定的session.过滤器需要事先定义好.</para>
<para><literal>(a)org.hibernate.annotations.FilterDef</literal> 或
<literal>@FilterDefs</literal> 定义过滤器声明,为同名过滤器所用.
-
过滤器声明带有一个name()和一个parameters()数组,<literal>@ParamDef</literal>包含name和type,
- 你还可以为给定的<literal>@filterDef</literal>定义一个defaultCondition()参数,
- 当<literal>@Filter</literal>中没有任何定义时,可使用该参数定义缺省条件.
+ 过滤器声明带有一个name()和一个parameters()数组. 参数提供了在运行时调整
+ 过滤器行为的能力,过滤器通过<literal>@ParamDef</literal>注解定义,该注解包含name和type,
+ 你还可以为给定的<literal>@FilterDef</literal>定义一个defaultCondition()参数,
+ 当所有的<literal>@Filter</literal>中没有任何定义时,可使用该参数定义缺省条件.
<literal>@FilterDef</literal> (s)可以在类或包一级进行定义.</para>
<para>现在我们来定义应用于实体或集合加载时的SQL过滤器子句.我们使用<literal>@Filter</literal>,并将其置于实体或集合元素上.</para>
@@ -2797,10 +2980,21 @@
@Filter(name="minLength", condition=":minLength <=
length")
} )
public class Forest { ... }</programlisting></para>
+
+ <para>当这些集合使用关联表来表示关系的时候,你可能需要对于关联表或者目标实体表应用
+ 过滤条件.使用<literal>@Filter</literal>注解可以在目标实体上添加改类约束.
+
但是如果你打算在关联表上使用,就需要使用<literal>(a)xn--filterjointable</literal>-f883ecz42b.</para>
+
+ <programlisting> @OneToMany
+ @JoinTable
+ //filter on the target entity table
+ @Filter(name="betweenLength", condition=":minLength <= length
and :maxLength >= length")
+ //filter on the association table
+ @FilterJoinTable(name="security", condition=":userlevel >=
requredLevel")
+ public Set<Forest> getForests() { ... }</programlisting>
</sect2>
-
- <sect2>
+ <sect2 id="entity-hibspec-query">
<title>查询</title>
<para>由于Hibernate引入了
@@ -2849,8 +3043,10 @@
</listitem>
</itemizedlist>
- <para>注意,EJB3已公开的最终草案中引入了<literal>@QueryHint</literal>的概念,
- 这可能是定义hints更好的方法.</para>
+ <para>通过<literal>@QueryHint</literal>注解可以在
+ <literal>(a)javax.persistence.NamedQuery</literal>
+ 中设置hints.另一个重要的优势是可以将这些注解应用到包上.</para>
+
</sect2>
</sect1>
Modified: trunk/HibernateExt/metadata/doc/reference/zh_cn/modules/lucene.xml
===================================================================
--- trunk/HibernateExt/metadata/doc/reference/zh_cn/modules/lucene.xml 2006-11-07 05:58:20
UTC (rev 10744)
+++ trunk/HibernateExt/metadata/doc/reference/zh_cn/modules/lucene.xml 2006-11-07 06:15:35
UTC (rev 10745)
@@ -1,19 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
-<chapter id="lucene">
- <title id="lucene">Hibernate与Lucene集成</title>
+<chapter id="lucene" revision="1">
+ <title>Hibernate与Lucene集成</title>
- <para>Lucene是一个高性能的java搜索引擎库,可以从 Apache软件基金组织获取。
- Hibernate Annotations包括一个注解包,它允许把任何域模型对象标记为可索引的,
- 并且对任何经由Hibernate进行持续化的实例,Hibernate 都会为之维护一个对应的Lucene索引。</para>
+ <para>Lucene是一个高性能的java搜索引擎库,可以从 Apache软件基金组织获取.
+ Hibernate Annotations包括一个注解包,它允许把任何域模型对象标记为可索引的,
+ 并且对任何经由Hibernate进行持续化的实例,Hibernate 都会为之维护一个对应的Lucene索引.</para>
- <sect1 id="lucene-intro">
- <title>使用Lucene为实体建立索引</title>
+ <para>Hibernate Lucene目前尚在进行中,新的特征也正在酝酿之中.因此后续版本将会有一些向前兼容的修改.</para>
- <sect2>
- <title>注解领域模型</title>
+ <section id="lucene-mapping">
+ <title>将实体映射到索引</title>
- <para>首先,必须将一个持久类声明为
- <literal>@Indexed</literal>:</para>
+
<para>首先,通过在类上标注<literal>@Indexed</literal>注解将一个持久类声明可索引化的类:</para>
<programlisting>@Entity
@Indexed(index="indexes/essays")
@@ -21,13 +19,14 @@
...
}</programlisting>
- <para>属性<literal>index</literal>是告诉Hibernate,
Lucene索引信息所在的位置(你文件系统的某个目录)。
-
如果你想为所有的Lucene索引定义一个根目录,你可以在配置文件中用属性<literal>hibernate.lucene.index_dir</literal>进行配置。
+ <para>属性<literal>index</literal>是告诉Hibernate,
Lucene的索引目录名(你文件系统的某个目录).
+ 如果你想为所有的Lucene索引定义一个根目录,你可以在配置文件中用属性
+ <literal>hibernate.lucene.default.indexDir</literal>进行配置.
</para>
- <para>Lucene索引包括四种字段:<emphasis>keyword</emphasis>
字段,<emphasis>text</emphasis>
-
字段,<emphasis>unstored</emphasis>字段和<emphasis>unindexed</emphasis>字段。
- Hibernate注解提供了将实体属性标记为前三种被索引字段的注解。</para>
+ <para>Lucene索引包括四种字段:<emphasis>keyword</emphasis>
字段,<emphasis>text</emphasis>
+
字段,<emphasis>unstored</emphasis>字段和<emphasis>unindexed</emphasis>字段.
+ Hibernate注解提供了将实体属性标记为前三种被索引字段的注解.</para>
<programlisting>@Entity
@Indexed(index="indexes/essays")
@@ -48,22 +47,110 @@
}</programlisting>
<para>这些注解定义了一个带有三个字段的索引:
- <literal>Id</literal>, <literal>Abstract</literal> 和
- <literal>Text</literal>.</para>
-
+ <literal>id</literal>, <literal>Abstract</literal> and
+ <literal>text</literal>.
+ 注意这些字段的第一个字母小写,字段的命名应遵守JavaBean命名规范.
+ </para>
+
<para>注意:你必须在你的实体类的标志属性上指定
<literal>@Keyword(id=true)</literal> .</para>
+
+ <para>Lucene具有<emphasis>boost factor</emphasis>的概念.
+ 在建索引的过程中,对于一个字段或一个索引元素给予更高的权重(相对其他字段或元素),
+ 你可以在类和字段上使用<literal>(a)xn--boost</literal>-zo21cm506a.</para>
+
+
<para>用于对元素建立索引的分析器类是可以通过<literal>hibernate.lucene.analyzer</literal>属性进行配置的.
+ 如果没有定义,则把
<classname>org.apache.lucene.analysis.standard.StandardAnalyzer</classname>作为缺省.</para>
-
<para>用于对元素建立索引的分析器类是可以通过<literal>hibernate.lucene.analyzer</literal>属性进行配置的。
- 如果没有定义,则把
<classname>org.apache.lucene.analysis.standard.StandardAnalyzer</classname>作为缺省。</para>
+ </section>
- </sect2>
+ <section id="lucene-configuration">
+ <title>配置</title>
- <sect2>
+ <section id="lucene-configuration-directory">
+ <title>目录配置</title>
+
+ <para>Lucene中具有存储索引的目录的概念.这些目录实现是可以定制的,
+ 而Lucene默认自带了一个文件系统实现以及一个完全内存实现.
+ 而Hibernate Lucene提供了<literal>DirectoryProvider</literal>,
+ 据此配置并初始化Lucence目录.</para>
+
+ <table>
+ <title>内置Directory Provider列表</title>
+
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry align="center">Class</entry>
+
+ <entry align="center">description</entry>
+
+ <entry align="center">Properties</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>org.hibernate.lucene.store.FSDirectoryProvider</entry>
+
+ <entry>基于文件系统的目录.用法为
+
&lt;indexBase&gt;/&lt;<literal>(a)Index.name</literal>&gt;</entry>
+
+ <entry><literal>indexBase</literal>: 基础目录</entry>
+ </row>
+
+ <row>
+ <entry>org.hibernate.lucene.store.RAMDirectoryProvider</entry>
+
+
<entry>基于内存的目录,可通过<literal>@Index.name</literal>元素唯一标识一个目录</entry>
+
+ <entry>none</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>如果内置的directory providers无法满足你的需要,你可以通过实现
+ <classname>org.hibernate.store.DirectoryProvider</classname>接口
+ 提供自己的directory provider.</para>
+
+ <para>每一个索引实体都和Lucene索引关联(一个索引可以在多个实体间共享,但是这种情况很少见).
+
你可以使用前缀为<literal><literal>hibernate.lucene.<indexname></literal></literal>
+ 的索引进行配置.
+ 所有的索引都会继承默认的属性,该属性的前缀为hibernate.lucene.default.</para>
+
+ <para>定义指定索引的directory provider,可使用
+
<literal>hibernate.lucene.<indexname>.directory_provider</literal></para>
+
+ <programlisting>hibernate.lucene.default.directory_provider
org.hibernate.lucene.store.FSDirectoryProvider
+hibernate.lucene.default.indexDir=/usr/lucene/indexes
+
+hibernate.lucene.Rules.directory_provider
org.hibernate.lucene.store.RAMDirectoryProvider
+</programlisting>
+
+ <para>applied on</para>
+
+ <programlisting>@Indexed(name="Status")
+public class Status { ... }
+
+@Indexed(name="Rules")
+public class Rule { ... }</programlisting>
+
+
<para>将会在<filename>/usr/lucene/indexes/Status</filename>之下创建一个文件系统目录,
+ 该目录下保存了所有的Status实体索引,而名为<literal>Rules</literal>
+ 的内存目录下则保存了所有的Rule实体索引.</para>
+
+ <para>因此你可以很轻松的定义通用的规则,例如directory provider和base directory,
+ 并在以后覆盖每一个基础索引(index basis)的默认值.</para>
+
+ <para>自定义的DirectoryProvider可以享受同样的配置机制.</para>
+ </section>
+
+ <section id="lucene-configuration-event">
<title>启用自动索引</title>
- <para>我们激活用于帧听三类Hibernate事件的
<literal>LuceneEventListener</literal>,
- 这些事件会在变更被提交至数据库后产生。</para>
+ <para>我们激活用于帧听三类Hibernate事件的
<literal>LuceneEventListener</literal>,
+ 这些事件会在变更被提交至数据库后产生.</para>
<programlisting><hibernate-configuration>
...
@@ -80,7 +167,7 @@
class="org.hibernate.lucene.event.LuceneEventListener"/>
</event>
</hibernate-configuration></programlisting>
- </sect2>
- </sect1>
+ </section>
+ </section>
</chapter>
Modified: trunk/HibernateExt/metadata/doc/reference/zh_cn/modules/setup.xml
===================================================================
--- trunk/HibernateExt/metadata/doc/reference/zh_cn/modules/setup.xml 2006-11-07 05:58:20
UTC (rev 10744)
+++ trunk/HibernateExt/metadata/doc/reference/zh_cn/modules/setup.xml 2006-11-07 06:15:35
UTC (rev 10745)
@@ -7,21 +7,21 @@
<itemizedlist>
<listitem>
- <para>首先从Hibernate官方网站下载并解压Hibernate Annotations的发布包。</para>
+ <para>首先从Hibernate官方网站下载并解压Hibernate Annotations的发布包.</para>
</listitem>
<listitem>
- <para><emphasis>这个版本(预览版)要求使用Hibernate
3.2.0.CR2或更高版本。请不要和老版本的Hibernate 3.x混合起来使用。</emphasis></para>
+ <para><emphasis>这个版本要求使用Hibernate 3.2.0.GA或更高版本.请不要和老版本的Hibernate
3.x混合起来使用.</emphasis></para>
</listitem>
<listitem>
- <para>这个版本在Hibernate core 3.2.0.CR2的基础上工作良好。</para>
+ <para>这个版本在Hibernate core 3.2.0.CR5和3.2.0.GA的基础上工作良好.</para>
</listitem>
<listitem>
- <para>首先确定你已经安装了JDK 5.0。当然就算使用低版本的JDK,
- Xdoclet也可以提供(基于注解的)元数据所带来的部分功能。
- 不过请注意本文档只描述跟JDK5.0注解有关的内容,关于Xdoclet请参考相关文档。</para>
+ <para>首先确定你已经安装了JDK 5.0.当然就算使用低版本的JDK,
+ Xdoclet也可以提供(基于注解的)元数据所带来的部分功能.
+ 不过请注意本文档只描述跟JDK5.0注解有关的内容,关于Xdoclet请参考相关文档.</para>
</listitem>
</itemizedlist>
</section>
@@ -29,24 +29,24 @@
<section id="setup-configuration">
<title>系统配置</title>
- <para>首先就是设置classpath(当然是在IDE中创建了一个新项目之后)。 <itemizedlist>
+ <para>首先就是设置classpath(当然是在IDE中创建了一个新项目之后). <itemizedlist>
<listitem>
-
<para>将Hibernate3核心文件以及其依赖的第三方库文件(请参考lib/README.txt文件)加入到你的classpath里面。</para>
+
<para>将Hibernate3核心文件以及其依赖的第三方库文件(请参考lib/README.txt文件)加入到你的classpath里面.</para>
</listitem>
<listitem>
<para>将<filename>hibernate-annotations.jar</filename>
-
和<filename>lib/ejb3-persistence.jar</filename>加入到你的classpath里面。</para>
+
和<filename>lib/ejb3-persistence.jar</filename>加入到你的classpath里面.</para>
</listitem>
<listitem>
- <para>如果要使用 <xref linkend="lucene"
/>,还需要将lucene的jar文件加入你的classpath。</para>
+ <para>如果要使用 <xref linkend="lucene"
/>,还需要将lucene的jar文件加入你的classpath.</para>
</listitem>
</itemizedlist></para>
<para>我们推荐在一个包装器(wrapper)类<classname>HibernateUtil</classname>
- 的静态初始化代码块中启动Hibernate。或许你在Hibernate文档的其他很多地方看到过这个类,
- 但是要在你的项目中使用注解,还需要对这个辅助(helper)类进行扩展。扩展如下:
+ 的静态初始化代码块中启动Hibernate.或许你在Hibernate文档的其他很多地方看到过这个类,
+ 但是要在你的项目中使用注解,还需要对这个辅助(helper)类进行扩展.扩展如下:
<programlisting>package hello;
import org.hibernate.*;
@@ -75,8 +75,8 @@
}
</programlisting></para>
-
<para>这里比较有意思的是使用到了<classname>AnnotationConfiguration</classname>类。
-
在XML配置文件(通常是<filename>hibernate.cfg.xml</filename>)中则定义了包和经过注解的类。下面的xml和前面的声明等价:
+
<para>这里比较有意思的是使用到了<classname>AnnotationConfiguration</classname>类.
+
在XML配置文件(通常是<filename>hibernate.cfg.xml</filename>)中则定义了包和经过注解的类.下面的xml和前面的声明等价:
</para>
<programlisting><!DOCTYPE hibernate-configuration PUBLIC
@@ -95,7 +95,7 @@
</hibernate-configuration>
</programlisting>
- <para>注意现在你可以混合使用hbm.xml和注解。资源元素(resource element)可以是hbm文件也可以是EJB3
XML发布描述符,此差别对于配置过程是透明的。</para>
+ <para>注意现在你可以混合使用hbm.xml和注解.资源元素(resource element)可以是hbm文件也可以是EJB3
XML发布描述符,此差别对于配置过程是透明的.</para>
<para>除了上面的方式,你还可以通过编程的方式定义包括注解的类和包</para>
@@ -107,23 +107,23 @@
.addAnnotatedClass(Dog.class)</emphasis>
.buildSessionFactory();</programlisting>
- <para>你也可以使用Hibernate Entity Manager来完成以上功能。Hibernate Entity
Manager有自己的一套配置机制,详情请参考相关文档。</para>
+ <para>你也可以使用Hibernate Entity Manager来完成以上功能.Hibernate Entity
Manager有自己的一套配置机制,详情请参考相关文档.</para>
- <para>除了启动方式和配置文件有所改变之外,结合注解来使用Hibernate API和以前没有什么区别,
- 在其他方面你还是可以继续保持以前的习惯和喜好(<filename>hibernate.properties</filename>,
- <filename>hibernate.cfg.xml</filename>, programmatic APIs等等)。
-
甚至对于同一个<classname>SessionFactory</classname>,你都可以混合带注解的持久类以及传统的bm.cfg.xml声明方式。
- 然而你不能多次声明同一个类(要么通过注解要么通过hbm.xml配置文件),
- 而且在一个映射实体的类继承层次中,这两个配置策略不能同时使用.
+ <para>除了启动方式和配置文件有所改变之外,结合注解来使用Hibernate API和以前没有什么区别,
+ 在其他方面你还是可以继续保持以前的习惯和喜好(<filename>hibernate.properties</filename>,
+ <filename>hibernate.cfg.xml</filename>, programmatic APIs等等).
+
甚至对于同一个<classname>SessionFactory</classname>,你都可以混合带注解的持久类以及传统的bm.cfg.xml声明方式.
+ 然而你不能多次声明同一个类(要么通过注解要么通过hbm.xml配置文件),
+ 而且在一个映射实体的类继承层次中,这两个配置策略不能同时使用.
</para>
- <para>为了简化从hbm文件到注解的迁移过程,
- 配置机制将自动检测在注解和hbm文件中重复的映射。
- 默认情况下hbm文件中的声明比类中的注解元数据具有更高的优先级。
- 这种优先级的设定是以类为单位的。
- 你也可以通过<literal>hibernate.mapping.precedence</literal>修改这种优先级。
- 默认的值是<literal>hbm, class</literal>,
- 如果改为<literal>class,hbm</literal>,当发生冲突的时候,类中的注解将比hbm文件具有更高的优先级。
+ <para>为了简化从hbm文件到注解的迁移过程,
+ 配置机制将自动检测在注解和hbm文件中重复的映射.
+ 默认情况下hbm文件中的声明比类中的注解元数据具有更高的优先级.
+ 这种优先级的设定是以类为单位的.
+ 你也可以通过<literal>hibernate.mapping.precedence</literal>修改这种优先级.
+ 默认的值是<literal>hbm,class</literal>,
+ 如果改为<literal>class,hbm</literal>,当发生冲突的时候,类中的注解将比hbm文件具有更高的优先级.
</para>
</section>
</chapter>
\ No newline at end of file
Modified: trunk/HibernateExt/metadata/doc/reference/zh_cn/modules/validator.xml
===================================================================
--- trunk/HibernateExt/metadata/doc/reference/zh_cn/modules/validator.xml 2006-11-07
05:58:20 UTC (rev 10744)
+++ trunk/HibernateExt/metadata/doc/reference/zh_cn/modules/validator.xml 2006-11-07
06:15:35 UTC (rev 10745)
@@ -2,23 +2,23 @@
<chapter id="validator">
<title>Hibernate验证器</title>
- <para>注解是一种为领域模型(domain model)指定不变约束的简洁而幽雅的方法。例如,你能
- 表示一个属性永远不为null,一个帐户余额一定是正值,等等。这些域模型约束通过为bean中的属性添加
- 注解来加以声明。随后一个验证器(validator)会读取并检查这些约束。验证机制可以执行于应用程序中的
- 不同层(表现层、数据访问层),而不必复述任何(前述)这些规则。Hibernate验证器正为这一目的而设计的。</para>
+ <para>注解是一种为领域模型(domain model)指定不变约束的简洁而幽雅的方法.例如,你能
+ 表示一个属性永远不为null,一个帐户余额一定是正值,等等.这些域模型约束通过为bean中的属性添加
+ 注解来加以声明.随后一个验证器(validator)会读取并检查这些约束.验证机制可以执行于应用程序中的
+ 不同层(表现层、数据访问层),而不必复述任何(前述)这些规则.Hibernate验证器正为这一目的而设计的.</para>
- <para>Hibernate验证器工作在两个层次上。第一层,它能检查内存中一个类的实例是否违反约束。
- 第二层,它能将约束应用于Hibernate元模型上,并将它们融入生成的数据库schema中。</para>
+ <para>Hibernate验证器工作在两个层次上.第一层,它能检查内存中一个类的实例是否违反约束.
+ 第二层,它能将约束应用于Hibernate元模型上,并将它们融入生成的数据库schema中.</para>
- <para>每个约束注解(constraint annotation)和一个验证器实现关联,该验证器负责检查位于实体实例上的约束。
- 一个验证器也能(可选地)将约束应用于Hibernate元模型上,让Hibernate生成表示这一约束的DDL。使用合适的事件监听器,你能
- 让Hibernate在插入和更新时执行检查操作。Hibernate验证器并不局限于同Hibernate一起使用。
- 你能在你应用程序的任何地方方便地使用它。</para>
+ <para>每个约束注解(constraint annotation)和一个验证器实现关联,该验证器负责检查位于实体实例上的约束.
+ 一个验证器也能(可选地)将约束应用于Hibernate元模型上,让Hibernate生成表示这一约束的DDL.使用合适的事件监听器,你能
+ 让Hibernate在插入和更新时执行检查操作.Hibernate验证器并不局限于同Hibernate一起使用.
+ 你能在你应用程序的任何地方方便地使用它.</para>
- <para>在运行时检查实例时,Hibernate验证器返回违反约束的信息,
- 这些信息以一个<classname>InvalidValue</classname>数组的形式返回。
- 除了众多其他信息外,<classname>InvalidValue</classname>包含了一个错误描述消
- 息,该信息可以内嵌与注解相捆绑的参数值(例如长度限制),以及能被提取至ResourceBundle的消息字串。</para>
+ <para>在运行时检查实例时,Hibernate验证器返回违反约束的信息,
+ 这些信息以一个<classname>InvalidValue</classname>数组的形式返回.
+ 除了众多其他信息外,<classname>InvalidValue</classname>包含了一个错误描述消
+ 息,该信息可以内嵌与注解相捆绑的参数值(例如长度限制),以及能被提取至ResourceBundle的消息字串.</para>
<sect1 id="validator-constraints">
<title>约束</title>
@@ -26,14 +26,14 @@
<sect2>
<title>什么是约束?</title>
- <para>约束通过注解表示。一个约束通常有一些用来参数化约束限制的属性。约束应用于带注解的元素。</para>
+ <para>约束通过注解表示.一个约束通常有一些用来参数化约束限制的属性.约束应用于带注解的元素.</para>
</sect2>
<sect2>
<title>内建约束</title>
- <para>Hibernate验证器有些内建约束,这些约束覆盖了大多数的基本数据检查。随后我们会看到,
- 你不必受制于这些内置约束,因为一分钟内就可以写出你自己的约束。</para>
+ <para>Hibernate验证器有些内建约束,这些约束覆盖了大多数的基本数据检查.随后我们会看到,
+ 你不必受制于这些内置约束,因为一分钟内就可以写出你自己的约束.</para>
<table>
<title>内建约束</title>
@@ -171,7 +171,7 @@
<entry>属性 (object)</entry>
-
<entry>对关联对象递归的进行验证。如果对象是集合或数组,就递归地验证其元素。如果对象是Map,则递归验证其值元素。</entry>
+
<entry>对关联对象递归的进行验证.如果对象是集合或数组,就递归地验证其元素.如果对象是Map,则递归验证其值元素.</entry>
<entry>无</entry>
</row>
@@ -179,9 +179,9 @@
<row>
<entry>@Email</entry>
- <entry>属性(String)</entry>
+ <entry>属性(String)</entry>
- <entry>检查字符串是否符合有效的email地址规范。</entry>
+ <entry>检查字符串是否符合有效的email地址规范.</entry>
<entry>无</entry>
</row>
@@ -193,21 +193,25 @@
<sect2 id="validator-constraints-error" xreflabel="Error
messages">
<title id="validator-constraints-error">错误信息</title>
+
+ <para>Hibernate验证器提供了一组默认的错误提示信息,它们被翻译成多种语言(如果你的语言不在其中,请给
+ 我们寄一个补丁).你可以创建<filename>ValidatorMessages.properties</filename>或
+ <filename>ValidatorMessages_loc.properties</filename>
+ 文件并改变相应的键值,籍此覆盖那些(默认)信息.你甚至可以在写自己的验证器
+ 注解时添加你自己的附加消息集.如果Hibernate无法从你自定制的resourceBundle
+ 或者ValidatorMessage中解析键值,就会使用内置的默认值.</para>
- <para>Hibernate验证器提供了一组默认的错误提示信息,它们被翻译成多种语言(如果你的语言不在其中,请给
-
我们寄一个补丁)。你可以在<filename>org.hibernate.validator.resources.DefaultValidatorMessages.properties</filename>
-
之外创建<filename>ValidatorMessages.properties</filename>或<filename>ValidatorMessages_loc.properties</filename>
- 文件并改变相应的键值,籍此覆盖那些(默认)信息。你甚至可以在写自己的验证器
- 注解时添加你自己的附加消息集。</para>
-
-
<para>或者你可以以编程方式检查bean的验证规则并提供相应的<classname>ResourceBundle</classname>。</para>
+
<para>或者你可以以编程方式检查bean的验证规则并提供相应的<classname>ResourceBundle</classname>,
+
如果你想使用完全不同的内插法,你可以自己实现<literal>org.hibernate.validator.MessageInterpolator</literal>
+ (详情请参考JavaDoc)
+ </para>
</sect2>
<sect2>
<title>编写你自己的约束</title>
- <para>扩展内建约束集是极其方便的。任何约束都包括两部分:约束<emphasis>描述符</emphasis>(注解)
- 和约束<emphasis>验证器</emphasis>(实现类)。下面是一个简单的用户定义描述符:</para>
+ <para>扩展内建约束集是极其方便的.任何约束都包括两部分:约束<emphasis>描述符</emphasis>(注解)
+ 和约束<emphasis>验证器</emphasis>(实现类).下面是一个简单的用户定义描述符:</para>
<programlisting>(a)ValidatorClass(CapitalizedValidator.class)
@Target(METHOD)
@@ -218,14 +222,14 @@
String message() default "has incorrect capitalization";
}</programlisting>
- <para><literal>type</literal>参数描述属性应该如何被大写。这是一个完全依赖于注解业务(逻辑)的用户
- 参数。</para>
+ <para><literal>type</literal>参数描述属性应该如何被大写.这是一个完全依赖于注解业务(逻辑)的用户
+ 参数.</para>
-
<para><literal>message</literal>是用于描述约束违规的默认字符串,它是强制要求的。你可以采取硬编码的方式,
- 或者通过Java ResourceBundle机制将message的部分/全部内容提取至外部文件。一旦发现message中{parameter}字符串,
- 就会在{parameter}这个位置注入相应的参数值(在我们的例子里Capitalization is not {type}会生成 Capitalization is
not FIRST),
- 可以将message对应的整个字符串提取至外部文件ValidatorMessages.properties,这也是一种良好实践。
- 见<xref linkend="validator-constraints-error" />。</para>
+
<para><literal>message</literal>是用于描述约束违规的默认字符串,它是强制要求的.你可以采取硬编码的方式,
+ 或者通过Java ResourceBundle机制将message的部分/全部内容提取至外部文件.一旦发现message中{parameter}字符串,
+ 就会在{parameter}这个位置注入相应的参数值(在我们的例子里Capitalization is not {type}会生成 Capitalization is
not FIRST),
+ 可以将message对应的整个字符串提取至外部文件ValidatorMessages.properties,这也是一种良好实践.
+ 见<xref linkend="validator-constraints-error" />.</para>
<programlisting>(a)ValidatorClass(CapitalizedValidator.class)
@Target(METHOD)
@@ -240,15 +244,15 @@
#in ValidatorMessages.properties
validator.capitalized=<literal>Capitalization is not
{type}</literal></programlisting>
- <para>如你所见{}符号是递归的。</para>
+ <para>如你所见{}符号是递归的.</para>
- <para>为了将一个描述符连接到它的验证器实现,我们使用<literal>@ValidatorClass</literal>
-
元注解。验证器类参数必须指定一个实现了<literal>Validator<ConstraintAnnotation></literal>
- 的类。</para>
+ <para>为了将一个描述符连接到它的验证器实现,我们使用<literal>@ValidatorClass</literal>
+
元注解.验证器类参数必须指定一个实现了<literal>Validator<ConstraintAnnotation></literal>
+ 的类.</para>
- <para>我们现在要实现验证器(也就是实现规则检查)。一个验证器实现能检查一个属性的值
- (实现<literal>PropertyConstraint</literal>),并且/或者可以修改hibernate映射元数据
-
(实现<literal>PersistentClassConstraint</literal>),籍此表示数据库级的约束。</para>
+ <para>我们现在要实现验证器(也就是实现规则检查).一个验证器实现能检查一个属性的值
+ (实现<literal>PropertyConstraint</literal>),并且/或者可以修改hibernate映射元数据
+
(实现<literal>PersistentClassConstraint</literal>),籍此表示数据库级的约束.</para>
<programlisting>public class CapitalizedValidator
implements Validator<Capitalized>, PropertyConstraint {
@@ -275,16 +279,16 @@
}
}</programlisting>
-
<para>如果违反约束,<literal>isValid()</literal>方法将返回false。更多例子请参考内建验证器实现。</para>
+
<para>如果违反约束,<literal>isValid()</literal>方法将返回false.更多例子请参考内建验证器实现.</para>
- <para>至此我们只看到属性级的验证,你还可以写一个Bean级别的验证注解。Bean自身会被传递给验证器,
- 而不是bean的属性实例。只要对bean自身进行注解即可激活验证检查。在单元测试套件中还可以找到一个小例子。</para>
+ <para>至此我们只看到属性级的验证,你还可以写一个Bean级别的验证注解.Bean自身会被传递给验证器,
+ 而不是bean的属性实例.只要对bean自身进行注解即可激活验证检查.在单元测试套件中还可以找到一个小例子.</para>
</sect2>
<sect2>
<title>注解你的领域模型</title>
- <para>既然你现在已经熟悉注解了,那么对语法也应该很清楚了。</para>
+ <para>既然你现在已经熟悉注解了,那么对语法也应该很清楚了.</para>
<programlisting>public class Address {
private String line1;
@@ -342,7 +346,7 @@
}
}</programlisting>
- <para>上面的例子只展示了公共属性验证,你还可以对任何可见度的字段(field)进行注解。</para>
+ <para>上面的例子只展示了公共属性验证,你还可以对任何可见度的字段(field)进行注解.</para>
<programlisting>@MyBeanConstraint(max=45)
public class Dog {
@@ -351,8 +355,8 @@
...
}</programlisting>
- <para>你可以对接口进行注解。Hibernate验证器会检查给定bean所扩展或实现的所有父类和接口,
- 籍以读取相应的验证器注解(信息)。</para>
+ <para>你可以对接口进行注解.Hibernate验证器会检查给定bean所扩展或实现的所有父类和接口,
+ 籍以读取相应的验证器注解(信息).</para>
<programlisting>public interface Named {
@NotNull String getName();
@@ -367,32 +371,32 @@
}</programlisting>
- <para>在验证Dog bean时会检查name属性的有效性(不为null)。</para>
+ <para>在验证Dog bean时会检查name属性的有效性(不为null).</para>
</sect2>
</sect1>
<sect1>
<title>使用验证器框架</title>
- <para>Hibernate验证器旨在实现多层数据验证,我们在一处表示约束(带注解的域模型),然后将其运用于
- 应用程序的不同层。</para>
+ <para>Hibernate验证器旨在实现多层数据验证,我们在一处表示约束(带注解的域模型),然后将其运用于
+ 应用程序的不同层.</para>
<sect2>
<title>数据库schema层次验证</title>
- <para>无须额外手续,Hibernate Annotations会自动将你为实体定义的约束翻译为映射元数据。例如,如果你的实体
- 的一个属性注解为<literal>@NotNull</literal>,在Hibernate生成的DDL schema中这列会被定义为
- <literal>not null</literal>。</para>
+ <para>无须额外手续,Hibernate Annotations会自动将你为实体定义的约束翻译为映射元数据.例如,如果你的实体
+ 的一个属性注解为<literal>@NotNull</literal>,在Hibernate生成的DDL schema中这列会被定义为
+ <literal>not null</literal>.</para>
</sect2>
<sect2>
<title>Hibernate基于事件的验证</title>
-
<para>Hibernate验证器有两个内建Hibernate事件监听器。当一个<literal>PreInsertEvent</literal>
- 或<literal>PreUpdateEvent</literal>发生时,监听器会验证该实体实例的所有约束,如有违反会抛出一个异常。
- 基本上,在Hibernate执行任何插入和更新前对象会被检查。这是激活验证过程的最便捷最简单的方法。当遇到约束
-
违规时,事件会引发一个运行时<classname>InvalidStateException</classname>,该异常包含一个描述每个错误的
- <literal>InvalidValue</literal>数组。</para>
+
<para>Hibernate验证器有两个内建Hibernate事件监听器.当一个<literal>PreInsertEvent</literal>
+ 或<literal>PreUpdateEvent</literal>发生时,监听器会验证该实体实例的所有约束,如有违反会抛出一个异常.
+ 基本上,在Hibernate执行任何插入和更新前对象会被检查.这是激活验证过程的最便捷最简单的方法.当遇到约束
+
违规时,事件会引发一个运行时<classname>InvalidStateException</classname>,该异常包含一个描述每个错误的
+ <literal>InvalidValue</literal>数组.</para>
<programlisting><hibernate-configuration>
...
@@ -407,29 +411,29 @@
</hibernate-configuration></programlisting>
<para><note>
- <para>在使用Hibernate Entity Manager时,Validation框架会被自动激活。如果bean不带验证注解,
- 就不会有性能损失。</para>
+ <para>在使用Hibernate Entity Manager时,Validation框架会被自动激活.如果bean不带验证注解,
+ 就不会有性能损失.</para>
</note></para>
</sect2>
<sect2>
<title>程序级验证</title>
- <para>Hibernate验证器能应用于你应用程序代码中的任何地方。</para>
+ <para>Hibernate验证器能应用于你应用程序代码中的任何地方.</para>
<programlisting>ClassValidator personValidator = new ClassValidator(
Person.class );
ClassValidator addressValidator = new ClassValidator( Address.class,
ResourceBundle.getBundle("messages", Locale.ENGLISH) );
InvalidValue[] validationMessages =
addressValidator.getInvalidValues(address);</programlisting>
- <para>头两行为执行类检查而准备Hibernate验证器。第一行依赖于嵌入在Hibernate验证器内的错误
- 消息(见<xref linkend="validator-constraints-error"
/>),第二行为这些消息准备资源包。这些代码只执行一次,
- 并将验证器进行缓存处理,这种方式是一种良好实践。</para>
+ <para>头两行为执行类检查而准备Hibernate验证器.第一行依赖于嵌入在Hibernate验证器内的错误
+ 消息(见<xref linkend="validator-constraints-error"
/>),第二行为这些消息准备资源包.这些代码只执行一次,
+ 并将验证器进行缓存处理,这种方式是一种良好实践.</para>
-
<para>第三行真正验证了<literal>Address</literal>实例并返回一个<literal>InvalidValue</literal>数组。
- 你的应用程序逻辑随后可以对错误做出响应。</para>
+
<para>第三行真正验证了<literal>Address</literal>实例并返回一个<literal>InvalidValue</literal>数组.
+ 你的应用程序逻辑随后可以对错误做出响应.</para>
- <para>除了针对整个bean你还可以对某个特定属性进行检查。这对于一个属性一个属性的用户交互情形或许是有用的。</para>
+ <para>除了针对整个bean你还可以对某个特定属性进行检查.这对于一个属性一个属性的用户交互情形或许是有用的.</para>
<programlisting>ClassValidator addressValidator = new ClassValidator(
Address.class, ResourceBundle.getBundle("messages", Locale.ENGLISH) );
@@ -443,12 +447,12 @@
<sect2>
<title>验证信息</title>
-
<para>作为一个验证信息的载体,hibernate提供了一个<classname>InvalidValue</classname>数组。
- 每个<literal>InvalidValue</literal>有一组,这些方法分别描述相应的个体问题。</para>
+
<para>作为一个验证信息的载体,hibernate提供了一个<classname>InvalidValue</classname>数组.
+ 每个<literal>InvalidValue</literal>有一组,这些方法分别描述相应的个体问题.</para>
-
<para><methodname>getBeanClass()</methodname>获取失败的bean类型。</para>
+
<para><methodname>getBeanClass()</methodname>获取失败的bean类型.</para>
- <para><methodname>getBean()</methodname>获取验证失败的实例(如果有的话,当使用
+ <para><methodname>getBean()</methodname>获取验证失败的实例(如果有的话,当使用
<methodname>getPotentianInvalidValues()</methodname>时则不会取到)
</para>
<para><methodname>getValue()</methodname>获取验证失败的值</para>
@@ -456,7 +460,7 @@
<para><methodname>getMessage()</methodname>获取合适的国际化错误消息</para>
<para><methodname>getRootBean()</methodname>获取产生问题的根bean实例(在与<literal>@Valid</literal>连用
- 时很有用),如用getPotentianInvalidValues()则返回null。</para>
+ 时很有用),如用getPotentianInvalidValues()则返回null.</para>
<para><literal>getPropertyPath()</literal>获取“问题”属性从根bean开始的带点的路径</para>
</sect2>
Modified: trunk/HibernateExt/metadata/doc/reference/zh_cn/modules/xml-overriding.xml
===================================================================
--- trunk/HibernateExt/metadata/doc/reference/zh_cn/modules/xml-overriding.xml 2006-11-07
05:58:20 UTC (rev 10744)
+++ trunk/HibernateExt/metadata/doc/reference/zh_cn/modules/xml-overriding.xml 2006-11-07
06:15:35 UTC (rev 10745)
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<chapter id="xml-overriding">
+<chapter id="xml-overriding" label="Overriding metadata through
XML">
<title>通过XML覆写元数据</title>
<para>在EJB3中元数据的主要目标是使用注释,但是EJB3规范也提供通过XML部署文件来覆写或者替换元数据注释.
@@ -8,7 +8,7 @@
<para>在测试套件中有一些附加的XML文件的样例.</para>
- <section>
+ <section id="xml-overriding-principles">
<title>原则</title>
<para>XML部署文件结构被设计为直接映射注释结构,所以如果你知道注释的结构,那么使用XML语法是很简单的.</para>
@@ -46,7 +46,7 @@
<para><literal>cascade-persist</literal> 意味着所有注释作为一个 cascade type
都是PERSIST的. 我们推荐你不要使用该特性.</para>
</section>
- <section>
+ <section id="xml-overriding-principles-entity"
revision="1">
<title>实体级别的元数据</title>
<para>你也可以在一个给定的实体上定义或者覆写元数据</para>
@@ -129,8 +129,10 @@
如果没有定义并且<literal>@Entity.name</literal>出现了的话,那么就使用该注释(假如metadata complete
没有被设置).</para>
<para>
- 对于metadata complete (参考下面)元素, 你可以定义一个
<literal>access</literal>(<literal>FIELD</literal> 或者
<literal>PROPERTY</literal>(默认值)),
- 对于非metadata complete 元素,使用注释的access type.</para>
+ 对于metadata complete(参考下面)元素, 你可以定义一个
<literal>access</literal>(<literal>FIELD</literal> 或者
<literal>PROPERTY</literal>(默认值)),
+ 对于非metadata complete元素,如果没有定义<literal>access</literal> ,则使用@Id注解的值,
+ 如果定义了<literal>access</literal>,则使用其对应的值.</para>
+
</callout>
<callout arearefs="aa4">
@@ -294,7 +296,7 @@
通过 <literal>id</literal>,
<literal>embedded-id</literal>,
<literal>version</literal>,
<literal>embedded</literal> 和
<literal>basic</literal>你可以覆写一个属性,
- 这些元素中的每一个元素都有相应的subelements:<literal>lob</literal>,
+ 这些元素中的每一个元素都有相应的subelements:<literal>lob</literal>,
<literal>temporal</literal>,
<literal>enumerated</literal>,
<literal>column</literal>.</para>