I'll reference myself for this one... I asked a related question in
http://forum.hibernate.org/viewtopic.php?t=974248 (to which unfortunately I haven't received any answer - I moreorless have figured it out myself anyway).
Quote:
Suppose you have two model objects : Page and Line. A page may have multiple lines, and a line must belong to exactly one page. I also want to put some ordering on the lines of a pages, since I obviously don't want them to appear in a random fashion. So far, I have the following tables (simplified for the sake of the example; the underlined columns are the primary keys) :
Page (page_id)
Line (line_id, page_id, line_number)
The "number" column identifies the position of a given line on a page. I assume there is no such thing as a "null" line, so the "number" values of the lines of any page is sequential (it won't be possible to have for a given page a line with number=3, another with number=5 but nothing with number=4). Also notice that (page_id, number) would be a perfectly valid composite primary key, but I chose to use a surrogate key instead. I added a constraint in my database that ensures the uniqueness of (page_id, line_number).
Some samples tuples for your table Line would be:
Code:
line_id | page_id | line_number
---------+---------+-------------
1 | 1 | 1
2 | 2 | 1
3 | 3 | 1
4 | 3 | 2
5 | 4 | 1
7 | 4 | 2
10 | 4 | 3
Now this situation is a perfect candidate for list mapping, because there is a
sequential ordering of the lines of a page.
In this specific case, the index column is "line_number". There is no way Hibernate could guess beforehands which column should be your index.
The base specifies where your index starts in the database (here it would be 1). This is important because you may have decided that your list is 1-based for instance in your database (like in this example); however, Java lists are
always 0-based.
If you specify base="0" but you actually start counting at 1, you would get a null when trying to access page.getLines().get(0) because there is no entry in Line with line_number = 0 - possibly raising NullPointerException afterwards when trying to access your lines.
However, if you indicate that your mapping is "1"-based, then Hibernate will shift the indexes such that page.getLines().get(0) points to the line entry with line_number = 1.
In other word, your base specifies by how much Hibernate should shift the value of the index column (in + ou - depending on which way you're going) to map it to the indexes of your Java list.
A working mapping for this example would be :
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="test">
<class name="Page" table="PAGE">
<id name="id" column="page_id">
<generator class="native">
<param name="sequence">page_page_id_seq</param>
</generator>
</id>
<property name="number" column="page_number" insert="false" update="false"/>
<list name="lines" lazy="false" cascade="all">
<key column="page_id" not-null="true"/>
<list-index base="1" column="line_number"/>
<one-to-many class="Line"/>
</list>
</class>
</hibernate-mapping>