Thursday, January 12, 2006

Regarding EJB 3.0 Entity lifecycle

EJB 3.0 Entities exist in one of 4 states: new, managed, detached, and removed.

The state transitions of an Entity depend upon the type of operations on the Entity and the life-cycles of associated Persistence and Transaction Contexts.

When an entity is first instantiated using Java new operator, its state is "new".

If you obtain an entity instance via EntityManager.find() or EntityManager.getReference(), or through a Query, its state depends upon whether there is an active Persistence Context or not. If there is one, then the Entity is in "managed" state, otherwise in "detached" state.

When you invoke EntityManager.persist() on a "new", "managed" or "removed" Entity, it becomes "managed". Note that you cannot invoke persist() on a "detached" Entity.

When you invoke EntityManager.merge() on a "new" or "detached" Entity, a "managed" copy of the Enity is created. You cannot invoke merge() on a "removed" Entity. Invoking merge() on a "managed" Entity leaves it in "managed" state.

When you invoke EntityManager.remove() on a "managed" Entity, its new state becomes "removed". Attempts to remove "new" or "removed" entities are ignored, however, it is an error to try and remove a "detached" entity.

If the Persistence Context is TRANSACTION scoped, then all "managed" entities within the Persistence Context become "detached" when the associated transaction ends. If the Persistence Context is scoped as EXTENDED, then the entities remain "managed" even after transaction ends.

In terms of Entity state, "new" and "detached" states are similar in that the Persistence Context has no knowledge of such entities.

The rules governing the lifecycle of Persistence Contexts are complex; I will explore them in another post.

The EntityManager interface provides two mechanisms for persisting an Entity: persist() and merge(). The differences between these two interfaces are subtle, and in my view, a single interface would have been better and less confusing. In terms of usage, I would recommend using merge() at all times.

1 comment:

Pestilence said...

Very helpful, thank you :)