1

I'm introducing JPA in an existing desktop application with a persistence layer where objects are extracted from the DB and stored back using plain queries.

After an object is extracted, it is used in the UI side to show it and to keep the user edits. When the user press the "save" button the persistence layer is invoked passing the object and it is stored back in the DB. If the user press the "cancel" button the modification are throw away and nothing happens in the persistence layer.

I'm replacing the plain query mechanism with JPA. The problem now is that when an object is retrieved using JPA it is managed. When the user modify it, the changes are stored directly in the DB.

I can't modify the UI code so the new persistence layer (JPA based) should emulate the old persistence layer (plain query based) behaviour.

How can I obtain it?

I was thinking to detach the objects before returning them from the persistence layer. In this case the user modifications are not persisted until the persistence layer is invoked.

In order to detach the object I can:

  • invoke the detach method in the EntityManager. This solution requires to annotate the relationships to get related object detached.
  • clear the EntityManager after each persistence layer operation.

Is the detach solution right? Which detach method is better?

Fedy2
  • 3,147
  • 4
  • 26
  • 44

1 Answers1

0

Yes, this is exactly the use case that the detach method addresses and I would definitely go with the first of your two approaches, the latter seems a little extreme and might have performance implications.

You should obviously be wary of lazy loaded relationships and make sure that all required objects have been fully initialised before you detach your object and expose it to your presentation layer or you'll come up against the dreaded LazyinitialisationException.

If you're using Hibernate as your implementation (and you're not too concerned with having a pure JPA implementation) then the following might prove useful in making sure all relationships are fully loaded before you detach:

public static <T> T initializeAndUnproxy(T entity) {
    if (entity == null) {
        return null;
    }
    if (entity instanceof HibernateProxy) {
        Hibernate.initialize(entity);
        entity = (T) ((HibernateProxy) entity).getHibernateLazyInitializer().getImplementation();
    }
    return entity;
}

source

StuPointerException
  • 7,117
  • 5
  • 29
  • 54