📄 persistent-classes.html
字号:
<tt class="literal">Session.merge()</tt> </p></li></ul></div><p> 我们建议你对持久化类声明命名一致的标识属性。我们还建议你使用一 个可以为空(也就是说,不是原始类型)的类型。 </p></div><div class="sect2" lang="zh-cn"><div class="titlepage"><div><div><h3 class="title"><a name="persistent-classes-pojo-final"></a>4.1.3. 使用非final的类 (可选)</h3></div></div><div></div></div><p> <span class="emphasis"><em>代理(proxies)</em></span>是Hibernate的一个重要的功能,它依赖的条件是,持久 化类或者是非final的,或者是实现了一个所有方法都声明为public的接口。 </p><p> 你可以用Hibernate持久化一个没有实现任何接口的<tt class="literal">final</tt>类,但是你 不能使用代理来延迟关联加载,这会限制你进行性能优化的选择。 </p><p> 你也应该避免在非final类中声明 <tt class="literal">public final</tt>的方法。如果你想使用一 个有<tt class="literal">public final</tt>方法的类,你必须通过设置<tt class="literal">lazy="false"</tt> 来明确地禁用代理。 </p></div><div class="sect2" lang="zh-cn"><div class="titlepage"><div><div><h3 class="title"><a name="persistent-classes-pojo-accessors"></a>4.1.4. 为持久化字段声明访问器(accessors)和是否可变的标志(mutators)(可选)</h3></div></div><div></div></div><p> <tt class="literal">Cat</tt>为它的所有持久化字段声明了访问方法。很多其他ORM工具直接对 实例变量进行持久化。我们相信,在关系数据库schema和类的内部数据结构之间引入间接层(原文为"非直接",indirection)会好一些。默认情况下Hibernate持久化JavaBeans风格的属性,认可 <tt class="literal">getFoo</tt>,<tt class="literal">isFoo</tt> 和 <tt class="literal">setFoo</tt>这种形式的方法名。 如果需要,你可以对某些特定属性实行直接字段访问。 </p><p> 属性<span class="emphasis"><em>不需要</em></span>要声明为public的。Hibernate可以持久化一个有 <tt class="literal">default</tt>、<tt class="literal">protected</tt>或<tt class="literal">private</tt>的get/set方法对 的属性进行持久化。 </p></div></div><div class="sect1" lang="zh-cn"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="persistent-classes-inheritance"></a>4.2. 实现继承(Inheritance)</h2></div></div><div></div></div><p> 子类也必须遵守第一条和第二条规则。它从超类<tt class="literal">Cat</tt>继承了标识属性。 </p><pre class="programlisting">package eg;public class DomesticCat extends Cat { private String name; public String getName() { return name; } protected void setName(String name) { this.name=name; }}</pre></div><div class="sect1" lang="zh-cn"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="persistent-classes-equalshashcode"></a>4.3. 实现<tt class="literal">equals()</tt>和<tt class="literal">hashCode()</tt></h2></div></div><div></div></div><p> 如果你有如下需求,你必须重载 <tt class="literal">equals()</tt> 和 <tt class="literal">hashCode()</tt>方法: </p><div class="itemizedlist"><ul type="disc" compact><li><p> 想把持久类的实例放入<tt class="literal">Set</tt>中(当表示多值关联时,推荐这么做) </p></li><li><p> 想重用脱管实例 </p></li></ul></div><p> Hibernate保证,仅在特定会话范围内,持久化标识(数据库的行)和Java标识是等价的。因此,一旦 我们混合了从不同会话中获取的实例,如果希望<tt class="literal">Set</tt>有明确的语义,就必 须实现<tt class="literal">equals()</tt> 和<tt class="literal">hashCode()</tt>。 </p><p> 实现<tt class="literal">equals()</tt>/<tt class="literal">hashCode()</tt>最显而易见的方法是比较两个对象 标识符的值。如果值相同,则两个对象对应于数据库的同一行,因此它们是相等的(如果都被添加到 <tt class="literal">Set</tt>,则在<tt class="literal">Set</tt>中只有一个元素)。不幸的是,对生成的标识不能 使用这种方法。Hibernate仅对那些持久化对象赋标识值,一个新创建的实例将不会有任何标识值。此外, 如果一个实例没有被保存(unsaved),并且它当前正在一个<tt class="literal">Set</tt>中,保存它将会给这个对象 赋一个标识值。如果<tt class="literal">equals()</tt> 和 <tt class="literal">hashCode()</tt>是基于标识值 实现的,则其哈希码将会改变,这违反了<tt class="literal">Set</tt>的契约。建议去Hibernate的站点阅读关于这个 问题的全部讨论。注意,这不是Hibernate的问题,而是一般的Java对象标识和Java对象等价的语义问题。 </p><p> 我们建议使用<span class="emphasis"><em>业务键值相等(Business key equality)</em></span>来实现<tt class="literal">equals()</tt> 和 <tt class="literal">hashCode()</tt>。业务键值相等的意思是,<tt class="literal">equals()</tt>方法 仅仅比较形成业务键的属性,它能在现实世界里标识我们的实例(是一个<span class="emphasis"><em>自然的</em></span>候选码)。 </p><pre class="programlisting">public class Cat { ... public boolean equals(Object other) { if (this == other) return true; if ( !(other instanceof Cat) ) return false; final Cat cat = (Cat) other; if ( !cat.getLitterId().equals( getLitterId() ) ) return false; if ( !cat.getMother().equals( getMother() ) ) return false; return true; } public int hashCode() { int result; result = getMother().hashCode(); result = 29 * result + getLitterId(); return result; }}</pre><p> 注意,业务键不必像数据库的主键那样固定不变(参见<a href="transactions.html#transactions-basics-identity" title="11.1.3. 关注对象标识(Considering object identity)">第 11.1.3 节 “关注对象标识(Considering object identity)”</a>)。 对业务键而言,不可变或唯一的属性是不错的选择。 </p></div><div class="sect1" lang="zh-cn"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="persistent-classes-dynamicmodels"></a>4.4. 动态模型(Dynamic models)</h2></div></div><div></div></div><p> <span class="emphasis"><em>注意,以下特性在当前处于试验阶段,将来可能会有变化。</em></span> </p><p> 运行期的持久化实体没有必要一定表示为像POJO类或JavaBean对象那样的形式。Hibernate也支持动态模型 (在运行期使用<tt class="literal">Map</tt>的<tt class="literal">Map</tt>)和象DOM4J的树模型那 样的实体表示。使用这种方法,你不用写持久化类,只写映射文件就行了。 </p><p> Hibernate默认工作在普通POJO模式。你可以使用配置选项<tt class="literal">default_entity_mode</tt>, 对特定的<tt class="literal">SessionFactory</tt>,设置一个默认的实体表示模式。 (参见<a href="session-configuration.html#configuration-optional-properties" title="表 3.3. 
 Hibernate配置属性
 ">表 3.3 “ Hibernate配置属性 ”</a>。) </p><p> 下面是用<tt class="literal">Map</tt>来表示的例子。首先,在映射文件中,要声明 <tt class="literal">entity-name</tt>来代替一个类名(或作为一种附属)。 </p><pre class="programlisting"><hibernate-mapping> <class entity-name="Customer"> <id name="id" type="long" column="ID"> <generator class="sequence"/> </id> <property name="name" column="NAME" type="string"/> <property name="address"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -