Collection Mapping Persistent Collections This section does not contain much example Java code. We assume you already know how to use Java's collections framework. If so, there's not really anything more to know - with a single caveat, you may use Java collections the same way you always have. Hibernate can persist instances of java.util.Map, java.util.Set, java.util.SortedMap, java.util.SortedSet, java.util.List, and any array of persistent entities or values. Properties of type java.util.Collection or java.util.List may also be persisted with "bag" semantics. Now the caveat: persistent collections do not retain any extra semantics added by the class implementing the collection interface (eg. iteration order of a LinkedHashSet). The Java type of a property holding a collection must be the interface type: Map, Set, List, or simply Collection; never HashMap, TreeSet or ArrayList. This restriction exists because, when you're not looking, Hibernate sneakily replaces your instances of Map, Set and List with instances of its own persistent implementations of Map, Set, or List. (So also be careful when using == on your collections.) You may therefore initialize a collection in your class with whatever implementation you find compatible. The persistent collections injected by Hibernate behave like HashMap, HashSet, TreeMap, TreeSet and ArrayList respectively. Of course, this depends on the mapping style you chose (ie. ordered or not, preserving position of elements, allowing duplicates, etc). Collections (not the contents) obey the usual rules for value types: no shared references, created and deleted along with the owning entity. Due to the underlying relational model, they do not support null value semantics; Hibernate does not distinguish between a null collection reference and an empty collection. Collections are automatically persisted when referenced by a persistent object and automatically deleted when unreferenced. If a collection is passed from one persistent object to another, its elements might be moved from one table to another. You shouldn't have to worry much about any of this. Just use Hibernate's collections the same way you use ordinary Java collections, but make sure you understand the semantics of bidirectional associations (discussed later) before using them. Collection instances are distinguished in the database by a foreign key to the owning entity. This foreign key is referred to as the collection key , on the table holding the collection elements. The collection key is mapped by the <key> element. If you have a foreign-key constraint set in the database, and have chosen the ON DELETE CASCADE option, always use the on-delete attribute on your <key> mappings: ]]> Collections may contain almost any other Hibernate type, including all basic types, custom types, components, and of course, references to other entities. This is an important definition: An object in a collection can either be handled with "pass by value" semantics (it therefore fully depends on the collection owner) or it can be a reference to another entity, with its own lifecycle. In this case, only the "link" between two objects is stored in the collection (non-Java developers call these links "pointers"). Collections may not contain other collections. The contained type is referred to as the collection element type. Collection elements are mapped by <element>, <composite-element>, or in the case of entity references, with <one-to-many>, <many-to-many>, or <many-to-any>. The first two map elements with value semantics, the other three are used to map entity associations. All collection mappings, except those with set and bag semantics, need an index column in the collection table - a column that maps to an array index, or List index, or Map key. The index of a Map may be of any basic type, it may be an entity reference, or even a composite type (it may not be a collection). The index of an array or list is always of type integer. Indexes are mapped using <index>, <index-many-to-many>, <composite-index>, or <index-many-to-any>. There are quite a range of mappings that can be generated for collections, covering many common relational models. We suggest you experiment with the schema generation tool to get a feeling for how various mapping declarations translate to database tables. Mapping a Collection Collections are declared by the <set>, <list>, <map>, <bag>, <array> and <primitive-array> elements. <map> is representative: ]]> name the collection property name table (optional - defaults to property name) the name of the collection table (not used for one-to-many associations) schema (optional) the name of a table schema to override the schema declared on the root element lazy (optional - defaults to true) enable lazy initialization (not available for arrays) inverse (optional - defaults to false) mark this collection as the "inverse" end of a bidirectional association cascade (optional - defaults to none) enable operations to cascade to child entities sort (optional) specify a sorted collection with natural sort order, or a given comparator class order-by (optional, JDK1.4 only) specify a table column (or columns) that define the iteration order of the Map, Set or bag, together with an optional asc or desc where (optional) specify an arbitrary SQL WHERE condition to be used when retrieving or removing the collection (useful if the collection should contain only a subset of the available data) fetch (optional, defaults to select) Choose between outer-join fetching and fetching by sequential select. Only one collection may be fetched by outer join per SQL SELECT. batch-size (optional, defaults to 1) specify a "batch size" for lazily fetching instances of this collection. access (optional - defaults to property): The strategy Hibernate should use for accessing the property value. The mapping of a List or array requires a seperate table column holding the array or list index (the i in foo[i]). If your relational model doesn't have an index column, e.g. if you're working with legacy data, use an unordered Set instead. This seems to put people off who assume that List should just be a more convenient way of accessing an unordered collection. Hibernate collections strictly obey the actual semantics attached to the Set, List and Map interfaces. List elements don't just spontaneously rearrange themselves! On the other hand, people who planned to use the List to emulate bag semantics have a legitimate grievance here. A bag is an unordered, unindexed collection which may contain the same element multiple times. The Java collections framework lacks a Bag interface, hence you have to emulate it with a List. Hibernate lets you map properties of type List or Collection with the <bag> element. Note that bag semantics are not really part of the Collection contract and they actually conflict with the semantics of the List contract (however, you can sort the bag arbitrarily, discussed later in this chapter). Note: Large Hibernate bags mapped with inverse="false" are inefficient and should be avoided; Hibernate can't create, delete or update rows individually, because there is no key that may be used to identify an individual row. Collections of Values and Many-To-Many Associations A collection table is required for any collection of values and any collection of references to other entities mapped as a many-to-many association (the natural semantics for a Java collection). The table requires (foreign) key column(s), element column(s) and possibly index column(s). The foreign key from the collection table to the table of the owning class is declared using a <key> element. ]]> column (required): The name of the foreign key column. For indexed collections like maps and lists, we require an <index> element. For lists, this column contains sequential integers numbered from zero. Make sure that your index really starts from zero if you have to deal with legacy data. For maps, the column may contain any values of any Hibernate type. ]]> column (required): The name of the column holding the collection index values. type (optional, defaults to integer): The type of the collection index. Alternatively, a map may be indexed by objects of entity type. We use the <index-many-to-many> element. ]]> column (required): The name of the foreign key column for the collection index values. class (required): The entity class used as the collection index. For a collection of values, we use the <element> tag. ]]> column (required): The name of the column holding the collection element values. type (required): The type of the collection element. A collection of entity references, where the references are held in a separate table corresponds to the relational notion of many-to-many association. ]]> column (required): The name of the element foreign key column. class (required): The name of the associated class. fetch (optional - defaults to join): enables outer-join or sequential select fetching for this association. This is a special case, for full eager fetching (in a single SELECT) of an entity and its many-to-many relationships to other entities, you would enable join fetching not only of the collection itself, but also with this attribute on the <many-to-many> nested element. Some examples, first, a set of strings: ]]> A bag containing integers (with an iteration order determined by the order-by attribute): ]]> An array of entities - in this case, a many to many association (note that the entities are lifecycle objects, cascade="all"): ]]> A map from string indices to dates: ]]> A list of components (discussed in the next chapter): ]]> One-To-Many Associations A one to many association links the tables of two classes directly, with no intervening collection table. (This implements a one-to-many relational model.) This relational model loses some of the semantics of Java collections: No null values may be contained in a map, set or list An instance of the contained entity class may not belong to more than one instance of the collection An instance of the contained entity class may not appear at more than one value of the collection index An association from Foo to Bar requires the addition of a key column and possibly an index column to the table of the contained entity class, Bar. These columns are mapped using the <key> and <index> elements described above. The <one-to-many> tag indicates a one to many association. ]]> class (required): The name of the associated class. Example: ]]> Notice that the <one-to-many> element does not need to declare any columns. Nor is it necessary to specify the table name anywhere. Very Important Note: If the <key> column of a <one-to-many> association is declared NOT NULL, Hibernate may cause constraint violations when it creates or updates the association. To prevent this problem, you must use a bidirectional association with the many valued end (the set or bag) marked as inverse="true". See the discussion of bidirectional associations later in this chapter. Sorted Collections Hibernate supports collections implementing java.util.SortedMap and java.util.SortedSet. You must specify a comparator in the mapping file: ]]> Allowed values of the sort attribute are unsorted, natural and the name of a class implementing java.util.Comparator. Sorted collections actually behave like java.util.TreeSet or java.util.TreeMap. If you want the database itself to order the collection elements use the order-by attribute of set, bag or map mappings. This solution is only available under JDK 1.4 or higher (it is implemented using LinkedHashSet or LinkedHashMap). This performs the ordering in the SQL query, not in memory. ]]> Note that the value of the order-by attribute is an SQL ordering, not a HQL ordering! Associations may even be sorted by some arbitrary criteria at runtime using a filter(). <literal>Using an <idbag></literal> If you've fully embraced our view that composite keys are a bad thing and that entities should have synthetic identifiers (surrogate keys), then you might find it a bit odd that the many to many associations and collections of values that we've shown so far all map to tables with composite keys! Now, this point is quite arguable; a pure association table doesn't seem to benefit much from a surrogate key (though a collection of composite values might). Nevertheless, Hibernate provides a feature that allows you to map many to many associations and collections of values to a table with a surrogate key. The <idbag> element lets you map a List (or Collection) with bag semantics. ]]> As you can see, an <idbag> has a synthetic id generator, just like an entity class! A different surrogate key is assigned to each collection row. Hibernate does not provide any mechanism to discover the surrogate key value of a particular row, however. Note that the update performance of an <idbag> is much better than a regular <bag>! Hibernate can locate individual rows efficiently and update or delete them individually, just like a list, map or set. In the current implementation, the native identifier generation strategy is not supported for <idbag> collection identifiers. Bidirectional Associations A bidirectional association allows navigation from both "ends" of the association. Two kinds of bidirectional association are supported: one-to-many set or bag valued at one end, single-valued at the other many-to-many set or bag valued at both ends Please note that Hibernate does not support bidirectional one-to-many associations with an indexed collection (list, map or array) as the "many" end, you have to use a set or bag mapping. You may specify a bidirectional many-to-many association simply by mapping two many-to-many associations to the same database table and declaring one end as inverse (which one is your choice, but it can not be an indexed collection). Here's an example of a bidirectional many-to-many association; each category can have many items and each item can be in many categories: ... ... ]]> Changes made only to the inverse end of the association are not persisted. This means that Hibernate has two representations in memory for every bidirectional association, one link from A to B and another link from B to A. This is easier to understand if you think about the Java object model and how we create a many-to-many relationship in Java: The non-inverse side is used to save the in-memory representation to the database. We would get an unneccessary INSERT/UPDATE and probably even a foreign key violation if both would trigger changes! The same is of course also true for bidirectional one-to-many associations. You may map a bidirectional one-to-many association by mapping a one-to-many association to the same table column(s) as a many-to-one association and declaring the many-valued end inverse="true". .... .... ]]> Mapping one end of an association with inverse="true" doesn't affect the operation of cascades, both are different concepts! Ternary Associations There are three possible approaches to mapping a ternary association. One approach is to use composite elements (discussed below). Another is to use a Map with an association as its index: ]]> ]]> A final alternative is to simply remodel the association as an entity class. This is the approach we use most commonly. Heterogeneous Associations The <many-to-any> and <index-many-to-any> elements provide for true heterogeneous associations. These mapping elements work in the same way as the <any> element - and should also be used rarely, if ever. Collection examples The previous sections are pretty confusing. So lets look at an example. This class: has a collection of eg.Child instances. If each child has at most one parent, the most natural mapping is a one-to-many association: ]]> This maps to the following table definitions: If the parent is required, use a bidirectional one-to-many association: ]]> Notice the NOT NULL constraint: On the other hand, if a child might have multiple parents, a many-to-many association is appropriate: ]]> Table definitions: For more examples and a complete walk-through a parent/child relationship mapping, see .