23 Nov
2008

NHibernate Fact when Saving a Transient Entity with Second Level Caching Enabled.

Category:UncategorizedTag: :

After attending the Advanced NHibernate workshop at the Kaizen Conference, I started to do some experimenting with NHibernate in order to gather more in dept knowledge about my favorite ORM tool. A topic that quite interests me about NHibernate, is its support for caching. NHibernate currently comes with 5 different caches:

  • Identity map (Session)
  • Entities cache (SessionFactory)
  • Collections cache (SessionFactory)
  • Timestamp cache (SessionFactory)
  • Query cache (SessionFactory)

The identity map is known as the first level cache, while the last four cache types in the list are all part of the second-level cache. Gabriel Schenker wrote a magnificent article on The NHibernate FAQ that provides a great overview of the different caching options available with NHibernate.

There is one point that I want to add to this article that may be unclear about using the second level cache. Gabriel mentions that when a transient entity is saved to the database, NHibernate automatically puts the date of the new entity into the second level cache. This is most certainly the case, but under one condition. A transient entity is added to the second-level cache only if its identifier is not automatically generated by the underlying database. Let me show a quick example.

Suppose I have an entity named User whose Id property is configured like the following:

    <id name="Id" type="Int32">
        <column name="Id"/>
        <generator class="native"/>
    </id>

When an new instance of User is saved in the database, NHibernate doesn’t put the data of the entity in the second level cache. When this particular entity is retrieved using a different session than the session that saved the new entity in the database, NHibernate issues a query to the DB instead of retrieving it from the second level cache.

Suppose we change the mapping of the Id property to something like this:


    <id name="Id" type="Int32">
        <column name="Id"/>
        <generator class="assigned"/>
    </id>

When retrieving this entity from a different session, NHibernate now reconstructs the entity from the data in the second level cache instead of sending a query to the database.

This little nuance had left me completely in the dark until I read this post on the NHibernate user group. In case of auto-generated identifiers, NHibernate doesn’t store the data of the transient entity into the second level cache because it has to hit the database anyway for retrieving the value of the corresponding identifier. Maybe this will change with NHibernate 2.1? Who knows?

I hope this clears things up.

3 thoughts on “NHibernate Fact when Saving a Transient Entity with Second Level Caching Enabled.

  1. Just another reason to manage your OIDs rather than letting NH assign them.

    Managing your OID rather than letting NHibernate manage it actually makes like significantly simpler. I use a base persistent entity class that assigns a guid for use as the OID and contains an integer version field so that NH can do the necessary transient / persistent checks (as well as allowing for concurrency management).

    IMHO letting NH manage your IDs, while correct from a “pure” POV (OID is a persistence concern, not a domain concern), causes more problems than it solves.

Comments are closed.