tags:

views:

10733

answers:

8

What would be the easiest way to detach a specific JPA Entity Bean that was acquired through an EntityManager. Alternatively, could I have a query return detached objects in the first place so they would essentially act as 'read only'?

The reason why I want to do this is becuase I want to modify the data within the bean - with in my application only, but not ever have it persisted to the database. In my program, I eventually have to call flush() on the EntityManager, which would persist all changes from attached entities to the underyling database, but I want to exclude specific objects.

+2  A: 

As far as I know, the only direct ways to do it are:

  1. Commit the txn - Probably not a reasonable option
  2. Clear the Persistence Context - EntityManager.clear() - This is brutal, but would clear it out
  3. Copy the object - Most of the time your JPA objects are serializable, so this should be easy (if not particularly efficient).
jsight
+1  A: 

If there aren't too many properties in the bean, you might just create a new instance and set all of its properties manually from the persisted bean.

This could be implemented as a copy constructor, for example:

public Thing(Thing oldBean) {
  this.setPropertyOne(oldBean.getPropertyOne());
  // and so on
}

Then:

Thing newBean = new Thing(oldBean);
mogrify
+3  A: 

Unfortunately, there's no way to disconnect one object from the entity manager in the current JPA implementation, AFAIR.

EntityManager.clear() will disconnect all the JPA objects, so that might not be an appropriate solution in all the cases, if you have other objects you do plan to keep connected.

So your best bet would be to clone the objects and pass the clones to the code that changes the objects. Since primitive and immutable object fields are taken care of by the default cloning mechanism in a proper way, you won't have to write a lot of plumbing code (apart from deep cloning any aggregated structures you might have).

Andrei
+9  A: 

(may be too late to answer, but can be useful for others)

I'm developing my first system with JPA right now. Infortunately I'm faced with this problem when this system is almost complete.

Simply put. Use Hibernate, or wait for JPA 2.0.

In Hibernate, you can use 'session.evict(object)' to remove one object from session. In JPA 2.0, in draft right now, there is the 'EntityManager.detach(object)' method to detach one object from persistence context.

Its now exactly one year later. I have this issue and I cannot find any "detach" method call on EntityManager. Was it dropped for some reason?
HDave
A: 

Mauricio Kanada, thanks to you for this advice, method evict() works nice. I use JPA from SEAM, there is built in support of JPA Entity Manager, and it is possible to access hibernate delegate Session and thus this method "evict".

Many thanks, Zmicer

+1  A: 

this is quick and dirty, but you can also serialize and deserialize the object.

davideconsonni
Just a heads up, this can cause issues with Lazy loading and JPA relationships.
James McMahon
A: 

I think you can also use method EntityManager.refresh(Object o) if primary key of the entity has not been changed. This method will restore original state of the entity.

trunikov
+3  A: 

If you need to detach an object from the EntityManager and you are using Hibernate as your underlying ORM layer you can get access to the Hibernate Session object and use the Session.evict(Object) method that Mauricio Kanada mentioned above.

public void detach(Object entity) {
    org.hibernate.Session session = (Session) entityManager.getDelegate();
    session.evict(entity);
}

Of course this would break if you switched to another ORM provider but I think this is preferably to trying to make a deep copy.

James McMahon