Monday, May 21, 2012

Entities and Proxy Objects in Hibernate

I would like to attempt and very simplistic explanation of the various states in which a JPA entity can exist.  I am going to consider this from my perspective using Hibernate and EJB 3, and other implementations may vary in some ways.

It is not my intent in this post to explain Persistence Contexts, Entity Managers, or any of the other numerous technologies involved.  I am simple going to give some insight in the states of entities and some thing that Hibernate allows you to do manage the state.

First of all a JPA entity is a managed object that is backed by a persistence store.  Meaning that the object can be 'saved' and later retrieved.  In EJB 3 the entities are POJOs annotated with @Entity.  In theory this is the simple part.  It becomes a bit more complex in implementation because of caching, lazy-loading, and detachment.

I am going to use three objects in my examples: Location, Store (which extends Location), and Suppliers (a Store has many Suppliers), and all relations are considered bidirectional.

Loaded

When an entity is managed by a persistence context it is 'loaded' into or 'managed' by that context.  The opposite of 'managed' or 'loaded' is detached.  There are two ways to get an entity in the 'loaded' state. (Please note that a Persistence Context is generally accessed and manipulated using an Entity Manager. I am going to refer to the theoretical context and ignore those implementation details here.)
  1. look the object up from a Persistence Context
  2. merge the object into a Persistence Context
Once you have a 'managed' entity it can be either a 'real' entity, meaning you actually have a Location for example, or it could be a proxy object that extends Location.  In either case you still have a 'managed' or 'loaded' object.

One thing to be careful of is that when you get a proxy object you know what you have.  For example if you retrieve a Store from the data store you might actually get a 'location proxy'.  A location proxy will have all the methods available from the Location, but it will not have any Store specific elements.

Initialized

To facilitate the lazy loading and caching the objects have a concept of 'initialized'.  An object that is 'initialized' can have all the getters and setters relevant to the Persistence Context called.  If you have a Location object and it is 'initialized' you can call getStores(), but those objects may not be initialized.