Wednesday, January 20, 2010

Section 4.5. Working with Simpler Collections








4.5. Working with Simpler Collections


The collections we've been looking at so far have all contained associations to other objects, which is
appropriate for a chapter titled "Collections and Associations," but these
aren't the only kind you can use with Hibernate. You can also define
mappings for collections of simple values, like strings, numbers, and
nonpersistent value classes.



4.5.1. How do I do that?


Suppose we want to be able to record some number of comments about
each track in the database. We want a new property called comments to contain the
String values of each associated comment. The new
mapping in Track.hbm.xml looks a
lot like what we did for artists, only a bit simpler[3]:

[3] If you're porting these examples to Oracle, you'll have to
change the name of the COMMENT column,
which turns out to be a reserved word in the world of Oracle
SQL. Standards—gotta love them—there are so many to
choose from!


<set name="comments" table="TRACK_COMMENTS">
<key column="TRACK_ID"/>
<element column="COMMENT" type="string"/>
</set>



(You can put this right before the closing <</class>> tag in the mapping file—and you
need to if you want the Track constructor to work
with the rest of this example.)


Since we're able to store an arbitrary number of comments for each
Track, we're going to need a new table in which
to put them. Each comment will be linked to the proper
Track through the track's id property.


Rebuilding the databases with ant
schema
shows how this gets built in the database:


[hibernatetool] create table TRACK_COMMENTS (TRACK_ID integer not null, COMMENT 
varchar(255));
...
[hibernatetool] 16:16:55,876 DEBUG SchemaExport:303 - alter table TRACK_COMMENTS
add constraint FK105B26882DCBFAB5 foreign key (TRACK_ID) references TRACK;


NOTE


Data modeling junkies will recognize this as a "one-to-many"
relationship.



After updating the Track class via ant codegen, we need to add another
Set at the end of each constructor invocation in
CreateTest.java, for the comments.
For example:


track = new Track("Test Tone 1",                                          
"vol2/singles/test01.mp3",
Time.valueOf("00:00:10"), new HashSet<Artist>(),
new Date(), (short)0, new HashSet<String>());



Then we can assign a comment on the following line:


track.getComments().add("Pink noise to test equalization");



A quick ant ctest will compile
and run this (making sure you've not forgotten to add the second
HashSet of strings to any tracks), and you can
check data/music.script to see how
it's stored in the database. Or, add another loop after the track
println⁠⁠(⁠ ⁠) in QueryTest.java to print the comments for the
track that was just displayed:


for (String comment : aTrack.getComments()) {                   
System.out.println(" Comment: " + comment);
}





Then ant qtest will give you
output like this:


...
[java] Track: "Test Tone 1" 00:00:10
[java] Comment: Pink noise to test equalization

It's nice when tools make simple things easier. In the next chapter we'll see that
more complex things are possible, too.










No comments: