返回介绍

自身关联

发布于 2025-04-21 21:42:12 字数 2203 浏览 0 评论 0 收藏

对象和数据表也可以关联到它们自身,这种关联叫做自身关联(reflexive association)。这种关联用于支持持久化递归结构的数据,例如树状结构,这种结构中的节点之间会彼此互相链接。数据库表中如果存储了这种关系的数据,要以 SQL 查询接口来检索这些数据将非常困难。所幸,将这种关联映射到 Java 对象后,处理就变得更容易理解和自然了。

在我们的音乐数据库中可能使用自身链接(reflexive link)的方式之一是让艺人可以有替换姓名(alternate name)。这一功能的用处可能会超出你的预期,因为如果让用户根据他们的思维方式来决定查找"The Smiths"或"Smiths, The",有了替换姓名就容易多了,只要一点点程序代码,而且实现方式与编程语言无关。

注意:我是指人类语言,英语、西班牙语或其他语言。在数据中放入这类链接,而不是试图去编写难以理解的程序代码来猜测何时应该调换艺人的姓名。

应该怎么做

需要做的事就是在 Artist.hbm.xml 里为 Artist 映射新增另一个字段,以建立一个指向 Artist 的链接。例 5-14 演示了一种配置方法。

例 5-14:在 Artist 类中建立自身关联

<many-to-one name="actualArtist"class="com.oreilly.hh.data.Artist">

<meta attribute="use-in-tostring">true</meta>

</many-to-one>

这个示例配置了一个 actualArtist 属性,在建立一个艺人的替换姓名时,我们可以将其设置为“实质的”Artist 记录的 id 值。例如,"The Smiths"记录的 id 值可能是 5,而它的 actualArtist 字段应该是 null,因为这个记录是实质的艺人记录。然后,我们随时都可以用"Smiths, The"这样的姓名创建“别名”Artist 记录,并将这个别名记录里的 actualArtist 字段设置为 5,以指向实质的记录。

有时,作为外键的字段不能按照其链接到的主键字段的名称来命名,自身链接就是这样的一个例子。我们将 ARTIST 表中的一行数据关联到 ARTIST 表中的另一行,当然,数据表中已经有名为 ARTIST_ID 的字段了。

为什么要将这种关联设置为多对一(many-to-one)类型的?也许会有很多别名记录会指向某个特定的实质 Artist 记录。所以,每个别名记录都必须保存实际艺人记录的 id,才能视其为替换姓名。用数据建模语言来说,这就是一种多对一关系。

查找艺人的代码只需要在返回前检查 actualArtist 属性。如果是 null,一切都没有问题;否则,就应该返回 actualArtist 属性指向的记录。例 5-15 扩展了 CreateTest 中的 getArtist()方法,以支持这种新功能(新增处以粗体字表示)。注意,Artist 构造函数多了一个用于设置 actualArtist 的新参数,所以,即使我们不用显示替换姓名,也得更新 CreateTest 中其他调用这个构造函数的各个地方。

例 5-15:支持替换姓名解析的艺人查询方法

public static Artist getArtist(String name, boolean create, Session session){

Query query=session.getNamedQuery("com.oreilly.hh.artistByName");

query.setString("name",name);

Artist found=(Artist)query.uniqueResult();

if(found==null&&create){

found=new Artist(name, new HashSet(),null);

session.save(found);

}

if(found!=null&&found.getActualArtist()!=null){

return found.getActualArtist();

}

return found;

}

希望这一章能让你感受到 Hibernate 中关联和集合的丰富而强大的功能。很明显,你可以结合这些功能,层层嵌套,当中的变化之多,恐怕我们难以在像这样的一本书中解释清楚。

好消息是 Hibernate 似乎已经相当完善,足以应付实际应用中可能会遇到的各种关联关系,甚至为你完成建立数据类和数据库模式,这样辛苦繁重的工作。当我开始创建这些示例时,Hibernate 工作的有效性和深远性远远超过了我的预期。

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。