Our first goal is to store the tracks that make up an album, keeping them in the right order. Later we'll add information like the disc on which a track is found, and its position on that disc, so we can gracefully handle multi-disc albums.
5.2.1 How do I do that?
The task of keeping a collection in a particular order is actually straightforward. If that's all we cared about in organizing album tracks, we'd need only tell Hibernate to map a List or array. In our Album mapping we'd use something like Example 5-2.
Example 5-2. Simple ordered mapping of tracks for an album
<list name="tracks" table="ALBUM_TRACKS"> <key column="ALBUM_ID"/> <index column="POSITION"/> <many-to-many class="com.oreilly.hh.Track" column="TRACK_ID"/> </list>
This is very much like the set mappings we've used so far (although it uses a different tag to indicate it's an ordered list and therefore maps to a java.util.List ). But notice that we also need to add an index tag to establish the ordering of the list, and we need to add a column to hold the value controlling the ordering in the database. Hibernate will manage the contents of this column for us, and use it to ensure that when we get the list out of the database in the future, its contents will be in the same order in which we stored them. The column is created as an integer, and if possible, it is used as part of a composite key for the table. The mapping in Example 5-2, when used to generate a HSQLDB database schema, produces the table shown in Example 5-3.
Example 5-3. Our simple track list realized as an HSQLDB schema
[schemaexport] create table ALBUM_TRACKS ( [schemaexport] ALBUM_ID INTEGER not null, [schemaexport] TRACK_ID INTEGER not null, [schemaexport] POSITION INTEGER not null, [schemaexport] primary key (ALBUM_ID, POSITION) [schemaexport] )
It's important to understand why the POSITION column is necessary. We need to control the order in which tracks appear in an album, and there aren't any properties of the tracks themselves we can use to keep them sorted in the right order. (Imagine how annoyed you'd be if your jukebox system could only play the tracks of an album in, say, alphabetical order, regardless of the intent of the artists who created it!) The fundamental nature of relational database systems is that you get results in whatever order the system finds convenient , unless you tell it how to sort them. The POSITION column gives Hibernate a value under its control that can be used to ensure that our list is always sorted in the order in which we created it. Another way to think about this is that the order of the entries is one of the independent pieces of information we want to keep track of, so Hibernate needs a place to store it.
The corollary is also important. If there are values in your data that provide a natural order for traversal, there is no need for you to provide an index column; you don't even have to use a list . The set and map collection mappings can be configured to be sorted in Java by providing a sort attribute, or within the database itself by providing a SQL order-by attribute. [5.1] In either case, when you iterate over the contents of the collection, you'll get them in the specified order.
[5.1] The order-by attribute and SQL sorting of collections is only available if you're using Version 1.4 or later of the Java SDK, since it relies on the LinkedHashSet or LinkedHashMap classes introduced in that release.
| || |
The values in the POSITION column will always be the same values you'd use as an argument to the tracks.get() method in order to obtain the value at a particular position in the tracks list.