Hibernate is a very mature and feature rich product that can be used to solve a lot of basic or advanced problems. One of its core features is the ability to map collections. If an entity contains a collection, for example a Map, Hibernate will map the entity and the map onto a relational structure (a number of tables) and allows the application to navigate through the collection without having to make explicit JDBC calls. Hibernate will under the hood perform the correct queries to fetch the data or even update rows in the database according to changes made by the application on the data structure in memory.

But what if you have a very large collection that you need to search for a single entry? For example, say the system is used to fetch the PostalCode a particular Street in a City. Fetching the complete collection of Streets and PostalCodes just to find out the PostalCode for a single street is not a very attractive idea. The normal approach would probably be to use a DAO and make an explicit query. Apart from the problem of getting the DAO object injected into the City entity, using a lazy Map is a more elegant solution.

Let’s look at some code examples.

Some essential parts of code (like constructors and the like) have been left out for simplicity.
Now how dow we map these structures? Lets look at the hibernate mapping.

The Map is mapped as a collection of composites. Also notice the lazy=”extra” setting used on the map. When we run the following test

The console shows the following:

First the two tables are created. The second table represents the Map with both components in it. The PK of this table is the FK to the containing entity and the columns representing the key in the map, in this case the STREET column that maps to the Street.name property.
The rows are inserted as expected.

Now when querying the data (we’re using a new session and a new entity instance) each get on the Map results in a new query on the database. If we do the same request twice, the same query is executed twice. This is because hibernate does not keep the Map in memory. For big collections this behavior can be very useful.

There are two drawbacks with this approach:
1. A collection mapped using Hibernate must always have an owner entity. The Map cannot be a standalone entity and it cannot be shared between entities. This can potentially lead to multiplying the relational structures if the data is used in several entities.
2. An extra lazy Map cannot be updated in an extra lazy fashion. This means that adding en entry to the Map or removing an entry from the Map will trigger Hibernate to load the complete Map into memory. Also, if components are used, Hibernate will not be able to detect changes to these objects, so this code

will not result in an update on the database. If the PostalCode class was promoted to an entity, Hibernate would be able to detect the changes and do the update.