Hi,
My question is more of a design issue than a technical problem. Part of it has been covered in the post
http://forum.hibernate.org/viewtopic.php?t=973053.
I 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) regardless of what Hibernate may or may not guarantee, since this database will also be accessed by non-Hibernate applications.
I want a bidirectional mapping between Line and Page, so it seems that I have two options to deal with this :
Either use a <list> mapping
Or use an <bag> with an "order by" clause (unless I'm mistaken an <idbag> mapping is useful for many-to-many mappings with a surrogate key, which is not the case here)
In either case, my understanding is that I'll need to specify inverse="false" and a not null constraint for the key column on the one-to-many side, and update="false" insert="false" on the many-to-one side (especially in the case of the list, where I feel that I
shouldn't have to deal with the index myself - this should be handled automatically by Hibernate and the list itself).
So on the whole, the mapping file should look like this for Line (in the case of the bag, I should probably drop the 'insert="false" update="false"' clauses for the 'number' property since I'm not sure the bag could automatically assign this property when I add an object to the "Lines" collection - in this case, I would have to assign it myself):
Code:
<class name="Line" table="LINE">
<id name="id" column="line_id">
<generator class="native">
<param name="sequence">line_line_id_seq</param>
</generator>
</id>
<property name="number" column="line_number" insert="false" update="false"/>
<many-to-one name="page" column="page_id" class="Page" insert="false" update="false" />
</class>
In the first case for Page:
Code:
<class name="Page" table="PAGE">
<id name="id" column="page_id">
<generator class="native">
<param name="sequence">page_page_id_seq</param>
</generator>
</id>
<list name="lines" lazy="true" cascade="all">
<key column="page_id" not-null="true" />
<list-index base="0" column="line_number" />
<one-to-many class="Line" />
</list>
</class>
Whereas in the second case:
Code:
<class name="Page" table="PAGE">
<id name="id" column="page_id">
<generator class="native">
<param name="sequence">page_page_id_seq</param>
</generator>
</id>
<bag name="lines" lazy="true" order-by="line_number" cascade="all">
<key column="page_id" not-null="true" />
<one-to-many class="Line" />
</bag>
</class>
My instinct tells me to use the first solution. Is this the correct way of doing it? Or is there any reason to prefer the second one, or even another way of doing it?