Monday, February 06, 2006

Hibernate mappings are Order-Sensitive

This won't mean much to most of you; I record it here so the search engines will be able to find it. I spent about a half day debugging a new Hibernate mapping (hbm.xml) file I just wrote. Maybe the next person to run into this will see this problem description before they spend that much time.

This is about the tenth mapping file I've written, so I'm starting to feel like I know what I'm doing. I am defining a mapping for an object that holds a Map (Java's Dictionary: look up an Object, indexed by another Object.) In order to store a Map in an RDB, you need columns for the Object holding the Map (to identify the particular Map in the DB), the key, and the value. Once I described the mapping, I got a compilation error. The error message said mainly:

Caused by: org.xml.sax.SAXParseException: The content of element type "map" must match "(meta*,subselect?,cache?,synchronize*, comment?,key,(map-key|composite-map-key| map-key-many-to-many|index|composite-index|index-many-to-many| index-many-to-any),(element|one-to-many|many-to-many| composite-element|many-to-any),loader?,sql-insert?,sql-update?, sql-delete?,sql-delete-all?,filter*)".

I re-read my description several times, read the documentation many time, searched for examples using map-key-many-to-many (found very few), and scratched my head a lot. Finally, I did find a sample use of map-key-many-to-many in a different section of the manual, and wondered whether the order of declaration could possiby matter. That turned out to be the problem. Somehow, I'd been following templates and not consciously noticed that XML documents described by a DTD are order-sensitive. If there's anything in the Hibernate documentation saying that it is order-sensitive, I missed it. If you swap the lines with map-key-many-to-many and many-to-many, it won't work.

<map name="positions" cascade="all" inverse="true">
    <key column="ACCOUNTS_ID"/>
    <map-key-many-to-many class="net.commerce.zocalo.claim.Position" />
    <many-to-many class="Coupons"/>
</map>

You can change the order of elements within a tag, but you can't change the order of the tags. Beware!

2 comments:

Anonymous said...

Hi Chris,

Thanks a lot! You just saved me a lot of work figuring out my hibernate issue. Google directed me to you blog right away when I entered the error message we both ran into.
Now at least I know it must be a minor bug in the software that generated my hbm.xml file.

Gertjan Idema

Anonymous said...

Yep. I only wasted 10 minutes. Thanks!