📄 persistent-classes.html
字号:
<html><head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Chapter 4. 持久化类(Persistent Classes)</title><link rel="stylesheet" href="../styles/html.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.60.1"><link rel="home" href="index.html" title="HIBERNATE - 符合Java习惯的关系数据库持久化"><link rel="up" href="index.html" title="HIBERNATE - 符合Java习惯的关系数据库持久化"><link rel="previous" href="session-configuration.html" title="Chapter 3. SessionFactory配置"><link rel="next" href="or-mapping.html" title="Chapter 5. O/R Mapping基础"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter 4. 持久化类(Persistent Classes)</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="session-configuration.html">Prev</a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="or-mapping.html">Next</a></td></tr></table><hr></div><div class="chapter" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="persistent-classes"></a>Chapter 4. 持久化类(Persistent Classes)</h2></div></div><div></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="persistent-classes-s1"></a>4.1. 简单示例</h2></div></div><div></div></div><p> 大多数java程序需要一个持久化类的表示方法。 </p><pre class="programlisting">package eg;import java.util.Set;import java.util.Date;public class Cat { private Long id; // identifier private Date birthdate; private Cat mate; private Set kittens private Color color; private char sex; private float weight; private void setId(Long id) { this.id=id; } public Long getId() { return id; } void setMate(Cat mate) { this.mate = mate; } public Cat getMate() { return mate; } void setBirthdate(Date date) { birthdate = date; } public Date getBirthdate() { return birthdate; } void setWeight(float weight) { this.weight = weight; } public float getWeight() { return weight; } public Color getColor() { return color; } void setColor(Color color) { this.color = color; } void setKittens(Set kittens) { this.kittens = kittens; } public Set getKittens() { return kittens; } // addKitten not needed by Hibernate public void addKitten(Cat kitten) { kittens.add(kitten); } void setSex(char sex) { this.sex=sex; } public char getSex() { return sex; }}</pre><p> 有三条主要的规则: </p><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="persistent-classes-s1-1"></a>4.1.1. 为持久化字段声明访问器(accessors)和是否可变的标志(mutators)</h3></div></div><div></div></div><p> <tt class="literal">Cat</tt>为它的所有可持久化字段声明了访问方法。很多其他ORM工具直接对实例变量进行持久化。我们相信在持久化机制中不限定这种实现细节,感觉要好得多。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可以对default,<tt class="literal">protected</tt>或者<tt class="literal">private</tt>的get/set方法对的属性一视同仁地执行持久化。 </p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="persistent-classes-s1-2"></a>4.1.2. 实现一个默认的构造方法(constructor)</h3></div></div><div></div></div><p> <tt class="literal">Cat</tt>有一个显式的无参数默认构造方法。所有的持久化类都必须具有一个默认的构造方法(可以不是public的),这样的话Hibernate就可以使用<tt class="literal">Constructor.newInstance()</tt>来实例化它们。 </p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="persistent-classes-s1-3"></a>4.1.3. 提供一个标识属性(identifier property)(可选) </h3></div></div><div></div></div><p> <tt class="literal">Cat</tt>有一个属性叫做<tt class="literal">id</tt>。这个属性包含了数据库表中的主关键字字段。这个属性可以叫任何名字,其类型可以是任何的原始类型、原始类型的包装类型、<tt class="literal">java.lang.String</tt> 或者是 <tt class="literal">java.util.Date</tt>。(如果你的老式数据库表有联合主键,你甚至可以用一个用户自定义的类,其中每个属性都是这些类型之一。参见后面的关于联合标识符的章节。) </p><p> 用于标识的属性是可选的。你可以不管它,让Hibernate内部来追踪对象的识别。当然,对于大多数应用程序来说,这是一个好的(也是很流行的)设计决定。 </p><p> 更进一步,一些功能只能对声明了标识属性的类起作用: </p><div class="itemizedlist"><ul type="disc" compact><li><p> 级联更新(Cascaded updates)(参阅“自管理生命周期的对象(Lifecycle Objects)”) </p></li><li><p> <tt class="literal">Session.saveOrUpdate()</tt> </p></li></ul></div><p> 我们建议你对所有的持久化类采取同样的名字作为标识属性。更进一步,我们建议你使用一个可以为空(也就是说,不是原始类型)的类型。 </p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="persistent-classes-s1-4"></a>4.1.4. 建议使用不是final的类 (可选)</h3></div></div><div></div></div><p> Hibernate的关键功能之一,<span class="emphasis"><em>代理(proxies)</em></span>,要求持久化类不是final的,或者是一个全部方法都是public的接口的具体实现。 </p><p> 你可以对一个<tt class="literal">final</tt>的,也没有实现接口的类执行持久化,但是不能对它们使用代理——多多少少会影响你进行性能优化的选择。 </p></div></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="persistent-classes-s2"></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="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="persistent-classes-s3"></a>4.3. 持久化生命周期(Lifecycle)中的回调(Callbacks)</h2></div></div><div></div></div><p> 作为一个可选的步骤,可持久化类可以实现<tt class="literal">Lifecycle</tt>接口,它可以提供一些用于回调的方法,可以让持久化对象在save或load之后,或者在delete或update之前进行必要的初始化与清除步骤。 </p><div class="programlistingco"><pre class="programlisting">public interface Lifecycle { public boolean onSave(Session s) throws CallbackException; <span class="co"><img src="../images/callouts/1.png" alt="(1)"></span> public boolean onUpdate(Session s) throws CallbackException; <span class="co"><img src="../images/callouts/2.png" alt="(2)"></span> public boolean onDelete(Session s) throws CallbackException; <span class="co"><img src="../images/callouts/3.png" alt="(3)"></span> public void onLoad(Session s, Serializable id); <span class="co"><img src="../images/callouts/4.png" alt="(4)"></span>}</pre><div class="calloutlist"><table border="0" summary="Callout list"><tr><td width="5%" valign="top" align="left"><img src="../images/callouts/1.png" alt="1" border="0"></td><td valign="top" align="left"><p> <tt class="literal">onSave</tt> - 在对象即将被save或者insert的时候回调 </p></td></tr><tr><td width="5%" valign="top" align="left"><img src="../images/callouts/2.png" alt="2" border="0"></td><td valign="top" align="left"><p> <tt class="literal">onUpdate</tt> - 在对象即将被update的时候回调(也就是对象被传递给<tt class="literal">Session.update()</tt>的时候) </p></td></tr><tr><td width="5%" valign="top" align="left"><img src="../images/callouts/3.png" alt="3" border="0"></td><td valign="top" align="left"><p> <tt class="literal">onDelete</tt> - 在对象即将被delete(删除)的时候回调 </p></td></tr><tr><td width="5%" valign="top" align="left"><img src="../images/callouts/4.png" alt="4" border="0"></td><td valign="top" align="left"><p> <tt class="literal">onLoad</tt> - 在对象刚刚被load(装载)后的时候回调 </p></td></tr></table></div></div><p> <tt class="literal">onSave()</tt>, <tt class="literal">onDelete()</tt> 和 <tt class="literal">onUpdate()</tt> 可以被用来级联保存或者删除依赖的对象。这种做法是在映射文件中声明级联操作外的另外一种选择。<tt class="literal">onLoad()</tt>可以用来让对象从其持久化(当前)状态中初始化某些暂时的属性。不能用这种方式来装载依赖的对象,因为可能无法在此方法内部调用<tt class="literal">Session</tt>接口。 <tt class="literal">onLoad()</tt>, <tt class="literal">onSave()</tt>和 <tt class="literal">onUpdate()</tt>另一种用法是用来在当前<tt class="literal">Session</tt>中保存一个引用,已备后用。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -