Struggling to understand EntityManager proper use

An entityManager manages a persistence context, in other word an in memory snapshot of the database state.

See What is a persistence object?

Every object loaded using the entityManager will be in managed state (see entity life cycle) until you close the EM. When an entity is managed, all change made to it will be tracked and then persisted when flushing the EM. If you access some lazy fetched attribute, a request will be automatically triggered to dynamically load the data, but if the entity is in detached state (if EM have been closed) accessing a lazy attribute will lead to the error you get.

The scope (/lifecycle) of your EM depends of your execution context. For a web application for example, an EM will typically be created for each http request.

For a standalone application, you have to mind if the database can be updated by another application/thread or not. If it can, your persistent context may not be consistent with the database state and you should create it for every unit of work (transaction) to avoid that. Otherwise you can create a single instance once for all the application lifecyle and flush it regulary.

For a CRUD app the lifecycle is generally the following :

  • create the EM
  • fetch some entities (they are so managed, any access to lazy attribute will load the data from DB)
  • close the EM (entity are now detached, any access to lazy attribute will lead to LazyInitializationException)
  • display the data to the user

On user updates validation :

  • create the em
  • open a transaction
  • merge (attach) your updated entities (this is what you call save) (if you have set up some optmistic locking, em will check the entity version against the database here)
  • eventually perform some business validation or additional updates
  • commit the transaction and close the em (changes will be flushed)

Keep is mind that EM is a lightweight object, cheap to create and destroy and NOT THREADSAFE.

BTW, JPA is a Java EE specification which is part of the EJB one (the persistence part). Its aim is to be used in a java EE container context (Java EE application server or CDI since JEE 6). You still can use hibernate in standalone mode through the JPA contract but even in this case, coupling with spring must be considered to take advantage of container managed features.

Leave a Comment