The remove is a "database state", as it denotates which is the state of the entity relative to the database - though it is not a "real" state but a programmed state, it will synchronize with db on next commit/flush -. It's equivalent to somethink like a persisted or merged state. The detached state is concerned about the state of the object relative to the persistence context ( EntityManager ). Detached has nothing to do with the entity's database state. A persisted entity can be detached.
For example.
EntityX x = new EntityX(); em.getUserTransaction().begin(); em.persist(x); em.getUserTransaction().commit(); // now the x object is detached.
Entity x = em.find(EntityX.class, 1); em.getUserTransaction().begin(); em.remove(x); // now x object is removed, but not detached. em.getUserTransaction().commit();
// x object is detached.
Hope it helps.
Helen Ge
Ranch Hand
Joined: May 24, 2005
Posts: 68
posted
0
Hi Pedro,
Your explaination always helps me! ( I remembered you helped me for my last question).
But I still feel a little foggy -
For your second example:
Entity x = em.find(EntityX.class, 1); em.getUserTransaction().begin(); em.remove(x); // now x object is removed, but not detached. em.getUserTransaction().commit();
// x object is detached.
right after the em.remove(x) call but before the commit() call, if we put the call em.persist(x), then the x will become managed again. Is it correct? But if we call persist(x) after the commit(), then the EntityExistsException will be thrown, right?
please bear with me if my question is not clear enough.
thanks
Helen Ge
SCJP SCWCD SCJWD
Pedro Erencia
Ranch Hand
Joined: Apr 03, 2008
Posts: 70
posted
0
Your explaination always helps me! ( I remembered you helped me for my last question).
I'm glad about it
right after the em.remove(x) call but before the commit() call, if we put the call em.persist(x), then the x will become managed again. Is it correct?
Yes, it is.
But if we call persist(x) after the commit(), then the EntityExistsException will be thrown, right?
I'm not 100% sure about that, but i think persist requires a transactional context to be executed. - supposing we are not using extended persistence contexts - if we do..
em.remove(x); // now x object is removed, but not detached. em.getUserTransaction().commit(); em.persist(x);
Did you test your example ? I'm not sure it will work (but I don't have a JPA compliant Application Server to test it).
For me, the entity x obtained in the first line is detached. As described in 3.1.1 EntityManager Interface
The find and getReference methods are not required to be invoked within a transaction context. If an entity manager with transaction-scoped persistence context is in use, the resulting entities will be detached;
And if you try to remove a detached entity, you'll have an IllegalArgumentException. As described in 3.2.2 Removal
If X is a detached entity, an IllegalArgumentException will be thrown by the remove operation (or the transaction commit will fail).
Can you confirm ? Thanks,
Beno�t
SCJP5 | SCBCD5 | SCEA5 Part 1
Pedro Erencia
Ranch Hand
Joined: Apr 03, 2008
Posts: 70
posted
0
Hi Beno�t,
yes, you're right. I didn't realize when i put the example, the find must be substituted by a new for the example to make sense, thanks and sorry .
Using a new entity insted of a find i've tested what i mentioned, and that's what i get..
Since I don't have the real life EJB experience and I don't have the JPA app server to test the code either, so what I am learning now is just based on the writing materials. Here I found the MZ's note regarding the persistence on the detached entities:
The semantics of the persist operation, applied to an entity X are as follows:
If X is a NEW entity, it becomes MANAGED. The entity X will be entered into the database at or before transaction commit or as a result of the flush operation.
If X is a preexisting MANAGED entity, it is IGNORED by the persist operation. However, the persist operation is cascaded to entities referenced by X, if the relationships from X to these other entities is annotated with the cascade=PERSIST or cascade=ALL annotation element value or specified with the equivalent XML descriptor element.
For all entities Y referenced by a relationship from X, if the relationship to Y has been annotated with the cascade element value cascade=PERSIST or cascade=ALL, the persist operation is applied to Y.
For your tested code #1
Can you let me know is this on the last line you got the TransactionRequiredException? I got confused with MZ's note, it says
If X is a DETACHED object, the EntityExistsException may be thrown when the persist operation is invoked
For your tested code #2
Can you tell me which line the PersistenceObjectException is thrown? Is this on the second em.persist(o) call?
if the em.clear() is detaching the object, then next em.persist(o) call should has the same effect as your code #1, why it throws different exception?
Study the persistent entity on SCBCD is the hardest part to me...
thanks
Helen Ge
SCJP SCWCD SCJWD
Pedro Erencia
Ranch Hand
Joined: Apr 03, 2008
Posts: 70
posted
0
Hi Helen,
For your tested code #1
code:
Order o=new Order(); context.getUserTransaction().begin(); o.setOrderName("S/W Order"); em.persist(o); context.getUserTransaction().commit(); em.persist(o);
Can you let me know is this on the last line you got the TransactionRequiredException? I got confused with MZ's note, it says
quote:If X is a DETACHED object, the EntityExistsException may be thrown when the persist operation is invoked
Yes, it's on the last line.
Also from MZ Study guide
The persist, merge, remove, and refresh methods MUST be invoked within a transaction context when an entity manager with a transaction-scoped persistence context is used. If there is no transaction context, the javax.persistence.TransactionRequiredException is thrown
For your tested code #2
code:
Order o=new Order(); context.getUserTransaction().begin(); o.setOrderName("S/W Order"); em.persist(o); em.clear(); em.persist(o); context.getUserTransaction().commit();
-------------------------------- A PersistentObjectException is thrown.
Can you tell me which line the PersistenceObjectException is thrown? Is this on the second em.persist(o) call?
Yes, it's on the second call to persist.
if the em.clear() is detaching the object, then next em.persist(o) call should has the same effect as your code #1, why it throws different exception?
In the second example the second call to persist is inside the boundaries of the transaction, so no TransactionRequired will be throw since there is a transaction; but since o is a detached entity your quote on MZs will apply.