返回介绍

有序集合

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

集合排序似乎与对象生命周期这一主题有些偏离,不过它确实是一个重要内容。这一章本来就打算介绍一些处理集合映射方面的有趣的技巧,所以我们就言归正传!现在我们的首要目标是存储组成专辑的曲目,并保证曲目的正确顺序。稍后,我们再加入曲目所属的唱片,以及曲目在该唱片的位置等信息,这样才可以妥善地处理包含多个唱片的专辑。

注意:喔,对,那就是我们试着要做的事……

应该怎么做

让集合内容保持特定的顺序其实相当简单。如果我们在组织专辑的曲目时只在乎这一点,那么只要告诉 Hibernate 映射到一个 List 或 Array 就可以了。例 5-2 演示了专辑(Album)映射中我们使用的方法。

例 5-2:专辑曲目的简单排序映射

<list name="tracks"table="ALBUM_TRACKS">

<key column="ALBUM_ID"/>

<list-index column="LIST_POS"/>

<many-to-many class="com.oreilly.hh.data.Track"column="TRACK_ID"/>

</list>

这与我们一直在用的 set 映射十分相似(虽然这里使用了一个不同的<list>标签以标明这个集合是个有序的列表,因此该集合会映射到一个 java.util.List 类)。但是要注意,我们也必须额外增加一个 list-index 标签,以建立这个列表的排序字段,同时,我们也必须在数据库中新增加一个字段来保存控制曲目顺序的值。Hibernate 会为我们管理这个字段的内容,用这个字段来确保将来从数据库把列表取出时,其内容会和当初存储到数据库时保持相同的顺序。这个字段的类型是整数,可能的话,可以将它作为该数据库表的组合主键(composite key)的一部分。当生成 HSQLDB 数据库模式定义时,就可以用例 5-2 的映射内容来生成例 5-3 所示的数据表。

例 5-3:简单有序曲目列表的 HSQLDB 模式定义

[hibernatetool]create table ALBUM_TRACKS(ALBUM_ID INTEGER not null,

TRACK_ID INTEGER not null, LIST_POS INTEGER not null,

primary key(ALBUM_ID, LIST_POS))

理解 LIST_POS 字段必不可少的原因是很重要的。我们需要控制曲目在专辑中出现的顺序,但是曲目自身并没有任何属性可以让我们确定它在专辑中的顺序(想象一下,如果播放器只能以字母顺序来播放专辑的曲目时,你会多么失望—竟然不能按照曲目的艺人顺序播放)。关系数据库系统的基本特性就是,检索得到的顺序是系统认为方便的顺序,除非指定了系统应该如何对结果进行排序。LIST_POS 字段给了 Hibernate 一个它可以进行控制的值,可以用于确保列表总是以当初创建的顺序进行排序的。另一种思考方式是,数据项的顺序是我们想保存下来的独立信息,所以 Hibernate 需要有个地方来保存它。

随之而来的结果也很重要。如果数据中有些值可以提供遍历的自然顺序,那就没有必要再提供一个索引字段(index column),甚至也不需要使用 list。set 和 map 集合映射标签就提供了一个 sort 属性,通过这个属性可以配置用于在 Java 中排序的字段,或者数据库本身也提供了一个用于排序的 SQL order-by 属性( [1] )。无论哪一种情况,当遍历集合的内容时,都能以特定的顺序获得其内容。

LIST_POS 字段中的值总是与传递给 tracks.get()方法的参数值相同,该方法用于获取 tracks 列表中某个特定位置上的值。

[1] 用 order-by 属性和 SQL 对集合进行排序的功能,只有 Java SDK 1.4 或更高版本才支持,因为这需要用到 1.4 版本以后才有的 LinkedHashSet 或 LinkedHashMap 类。

发布评论

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