- 译者序
- 前言
- 本书怎么使用
- 本书排版字体约定
- 本书网站
- 致谢
- 第一部分 Hibernate 快速入门
- 第 1 章 安装和设置
- 第 2 章 映射简介
- 第 3 章 驾驭 Hibernate
- 第 4 章 集合与关联
- 第 5 章 更复杂的关联
- 第 6 章 自定义值类型
- 第 7 章 映射标注
- 第 8 章 条件查询
- 第 9 章 浅谈 HQL
- 第二部分 与其他工具的集成
- 第 10 章 将 Hibernate 连接到 MySQL
- 第 11 章 Hibernate 与 Eclipse:Hibernate Tools 使用实战
- 第 12 章 Maven 进阶
- 第 13 章 Spring 入门:Hibernate 与 Spring
- 第 14 章 画龙点睛:用 Stripes 集成 Spring 和 Hibernate
- 附录 A Hibernate 类型
- 附录 B Criteria API
- 附录 C Hibernate SQL 方言
- 附录 D Spring 事务支持
- 附录 E 参考资源
- 作者简介
- 封面介绍
另一种方法
这个试验表明标注确实是一种映射模型类的可行方法。通过为数不多的几步,我们就可以精确地维护前面章节中逐步建立的数据库模式,只是标注这种方法不能让我们在创建 Album 时级联创建 Track 对象。如果以稍微不同的方式来考虑 AlbumTrack 类,则还有另一种方法,让我们在数据库模式中能够维护这种自动的级联处理,同时也提供了一些其他功能。
将 AlbumTrack 映射为一个完整的实体,我们就可以添加级联标注,Hibernate 就会优先处理 Album 定义,以嵌入对 Track 的引用。这也给我们带来一些新的需要考虑的复杂问题,但其中一部分需要视不同的时机而定夺。首先,将 AlbumTrack 作为实体就需要具有 ID。同时,因为我们接着需要不从 Album 开始就可以处理 AlbumTrack 对象,所以应该扩充 AlbumTrack 模型,以提供从 ALBUM_TRACKS 表返回到 ALBUM 表的链接(我们将它用于 Hibernate 复合键)。为此,需要增加一个 album 属性。例 7-12 演示了 AlbumTrack 映射中关键的一部分,也是这种方法的独特之处所在。
例 7-12:将 AlbumTrack 类标注为实体
package com.oreilly.hh.data;
import java.io.Serializable;
import javax.persistence.*;
@Entity❶
@Table(name="ALBUM_TRACKS")
public class AlbumTrack{
@Id❷
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
@ManyToOne
@JoinColumn(name="ALBUM_ID",insertable=false, updatable=false,❸
nullable=false)
private Album album;
@ManyToOne(cascade=CascadeType.ALL)❹
@JoinColumn(name="TRACK_ID",nullable=false)
private Track track;
……
public Integer getId(){
return id;
}
public void setId(Integer id){
this.id=id;
}
public Album getAlbum(){
return album;
}
❺
public Track getTrack(){
……
}
❶明显地,我们将类标注由 @Embeddable 修改为 @Entity,而且就在这里选择了表名,而不是在 Album 类的源文件中。
❷此处与基于 XML 的例子中的模式差别最大。以前我们的 ALBUM_TRACK 表使用一个复合主键,利用的是 ALBUM_ID 和 TRACK_ID 的一个特定组合在数据库中只有一个记录这一事实,这样就节省了我们在 ALBUM_TRACK 表中提供一个单独的 ID 列的需要。
虽然让 AlbumTrack 成为一个实体后还保留原来的数据库模式也是可能的,不过这需要付出不少的努力。JPA 要求所有的复合主键都要被映射为一个单独的类,由这个类来提供一个主键的各个成员。所以,为了保留原来我们的数据库模式,就必须对模型类进行比较大的修改,只是为了持有 AlbumTrack 类的主键而创建一个新的类。
相反,也可以稍微修改一下数据库模式,为 ALBUM_TRACKS 增加一个 ID 列(应该承认,这个列没有什么实际用途),看起来是一种破坏力比较小的选择。无论如何,当改变映射方法时,我们将要面对各种权衡,这个例子就是一个有趣的演示。
❸到 Album 的映射是我们以前见过的 @ManyToOne,但是还需要提供一些额外的参数,才能让它按我们想要的方式来工作。这段“咒语”用于重新创建我们曾经用 Album.hbm.xml 取得的映射效果,让 Hibernate 完全控制对 ALBUM_TRACKS 表的 ALBUM_ID 列的维护。如果没有 @JoinColumn 标注中的 insertable 和 updatable 属性,我们就得必须修改 AlbumTest,为每个 AlbumTrack 对象显式地设置 album 属性,这样也就意味着失去了一些我们想要从 Hibernate 得到的自动处理。
当使用实体上的索引映射时(具有 @IndexColumn 或 @MapKey),你应该记住这种应用模式。
❹既然 AlbumTrack 是一个实体,Hibernate 就能够为它的 track 属性应用 cascade 的设置。
❺我们可以强化一个概念,Hibernate 在管理到专辑的链接(album 属性)时,并没有使用 setAlbum()方法。
当然,在 Album.java 中这一关系的映射方式也会有稍微的不同,如例 7-13 所示。
例 7-13:Album.java 中的 AlbumTracks 实体映射
……
@OneToMany(cascade=CascadeType.ALL)
@IndexColumn(name="LIST_POS")
@JoinColumn(name="ALBUM_ID",nullable=false)
private List<AlbumTrack>tracks;
……
@OneToMany 标注中的级联(cascade)设置,它通过 Album 中嵌入的 Track 引用来建立这种完整的级联关系,我们在例 5-13 开发的 Album.hbm.xml 最终版本中也曾经建立过这样的关联,在那个例子中是由专辑对象来管理它们的曲目对象的生命周期。在这里,需要再一次将 AlbumTest 的 addAlbumTrack()方法中用于保存曲目的那行代码注释掉。这样,我们用不同的数据库模式重新创建了原来的功能。如果不怕麻烦,也可以创建一个类来负责管理复合键,这样就可以保留原来的功能和数据库模式。
和许多其他 Hibernate API(以及一般的面向对象的建模方法)一样,可以用多种方法来实现一个功能。
现在怎么办
希望这一章可以让你对如何用标注来表达数据映射有个大致的了解,也希望当你为自己的项目探索新的选择时,本章介绍的内容可以作为一个良好的起点。在本书接下来的部分,我们将不列举相关技术的所有细节和功能(这应该是 Hibernate 参考手册的任务),虽然有时介绍的比较肤浅,但希望我们讨论的一些问题可以作为帮助你解决模糊问题的示例。如果所有办法都解决不了问题,那只能尝试让问题重新出现,再将错误消息粘贴到 Google 上搜索!或者,如果你是好“公民”的话,可以研究一下源代码,将问题发布到 Hibernate 论坛上以寻求帮助,把解决问题的希望留给未来的用户,并帮助突出应该加强 Hibernate 文档的哪些部分。
在接下来的几章中,我们将继续回到基于 XML 的世界,看看几种查询数据的方法。但是,还应该记住标注的概念,在本书结尾部分介绍 Spring 和 Stripes 的章节中,将会再次用到它们。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论