5.4 Lifecycle Associations
Hibernate is completely responsible for managing the
table, adding and deleting rows (and, if necessary,
values) as entries are added to or removed from
properties. You can test this by writing a test program to delete the second track from our test album and see the result. A very quick and dirty way to do this would be to add the following four lines (see Example 5-11) right after the existing
line in Example 5-7 and then run
ant schema ctest atest db
Example 5-11. Deleting our album's second track
tx = session.beginTransaction();
Doing so changes the contents of
as shown in Figure 5-4 (compare this with the original contents in Figure 5-3). The second record has been removed (remember that Java list elements are indexed starting with zero), and
has been adjusted so that it retains its consecutive nature, corresponding to the indices of the list elements (the values you'd use when calling
Figure 5-4. Album track associations after deleting our album's second track
This happens because Hibernate understands that this list is 'owned' by the
record, and that the 'lifecycles' of the two objects are intimately connected. This notion of lifecycle becomes more clear if you consider what happens if the entire
is deleted: all of the associated records in
will be deleted as well. (Go ahead and modify the test program to try this if you're not convinced.)
Contrast this with the relationship between the
table and the
table. Tracks are sometimes associated with albums, but they are sometimes independent. Removing a track from the list got rid of a row in
, eliminating the link between the album and track, but didn't get rid of the row in
, so it didn't delete the persistent
object itself. Similarly, deleting the
would eliminate all the associations in the collection, but none of the actual
. It's the responsibility of our code to take care of that when appropriate (probably after consulting the
, in case any of the track records might be shared across multiple albums, as discussed above).
If we don't need the flexibility of sharing the same track between albums ”disk space is pretty cheap lately given the
of compressed audio ”we can let Hibernate manage the
records for the album in the same way it does the
collection. It won't assume it should do this, because
objects can exist independently, but we can establish a lifecycle relationship between them in the album mapping document.
By now you're probably not surprised there's a way to automate this.
5.4.1 How do I do that?
Example 5-12 shows (in bold) the changes we'd make to the
property mapping in
Example 5-12. Establishing a lifecycle relationship between an album and its tracks
<list name="tracks" table="ALBUM_TRACKS"
<many-to-one name="track" class="com.oreilly.hh.Track"
<property name="disc" type="integer"/>
<property name="positionOnDisc" type="integer"/>
Hibernate that you want operations performed on a 'parent' object to be transitively applied to its 'child' or 'dependent' objects. It's
to all forms of collections and associations. There are several possible values to choose among. The most common are
). You can also change the default from
throughout your entire mapping document by supplying a
attribute in the
In our example, we want the tracks owned by an album to be automatically managed by the album, so that when we delete the album, its tracks are deleted. Note that we need to apply the
attribute both to the
collection and its
element to achieve this. Also, by using a
, we eliminate the need to explicitly save any
objects we create for the album ”the
method of Example 5-7 no longer needs the line:
By telling Hibernate that it's fully responsible for the relationship between an album and its track, we enable it to persist tracks when they're added to the album as well as delete them when the album itself is deleted.
of bookkeeping to the mapping layer can be very
, freeing you to focus on more abstract and important
, so it is worth using when appropriate. It's reminiscent of the liberation provided by Java's pervasive garbage collection, but it can't be as comprehensive because there is no definitive way to know when you're finished with persistent data by performing reachability analysis; you need to
it by calling
and establishing lifecycle connections. The trade-off between flexibility and simple automation is yours to make, based on the nature of your data and the needs of your project.
Hibernate's management of lifecycle relationships is not foolproof ”or perhaps it's more accurate to say it's not all-encompassing. For example, if you use
to remove a
property, this breaks the link between the
actually delete the
record. Even if you later delete the entire
, because it wasn't linked to the
at the time that it was deleted. Try some of these experiments by modifying
appropriately and look at the resulting data in the tables!