There are always so many questions related to issues with detached entities!
First, they often cause LazyInitializationException
in Hibernate.
Yes, there are another persistence providers, which don't throw exceptions,
but I think that they have some problems with consistency.
Consider we have A
and B
entities that there is reference
(@ManyToOne
) from A
to B
that is required to be non-null.
We started our session, loaded A
instance and then closed session.
After that we try to obtain a reference to B
.
And assume that another transaction just deleted both our A
and B
instances. So when we query from database we can't find appropriate B
instance and get null
!
So our contract is violated. Some code that relies on fact that
a.getB()
returns an object will throw an NullPointerException
.
With persistent entities this is impossible because we have all lazy
loading in the same transaction with obtaining object itself,
so all operations are atomic (if we have a proper transaction isolation of course).
Also there are problems when you want to store persistent and detached entities in one Set
. It that case you should always override equals
and hashCode
, which usually looks awkward, as I can't see a really good way to do it.
To get a detached entity back into EntityManager
you should use merge
which is glitchy.
So my question is: is there is a reasonable scenario where detached entities are really needed? Furthermore, when do you have to mix detached and persistent entities
and merge detached entities into a new EntityManager
?
A detached entity (a.k.a. a detached object) is an object that has the same ID as an entity in the persistence store but that is no longer part of a persistence context (the scope of an EntityManager session).
When the transaction (in transaction-scoped persistence context) commits, entities managed by the persistence context become detached. If an application-managed persistence context is closed, all managed entities become detached. Using clear method.
detach. Remove the given entity from the persistence context, causing a managed entity to become detached. Unflushed changes made to the entity if any (including removal of the entity), will not be synchronized to the database. Entities which previously referenced the detached entity will continue to reference it.
Entity. Entities in JPA are nothing but POJOs representing data that can be persisted to the database. An entity represents a table stored in a database. Every instance of an entity represents a row in the table.
I will explain why that scenario should not occur and why we need detached entities.
Consider you are in a JTA transaction (JPA requires support for it) and fetch a
.
Now you can call a.getB()
either (1) in this transaction (i.e entity a
is managed) or (2) when a
is detached.
Scenario 1: now depending on your transaction isolation level, you might see or might not see what other transactions do. For example, if you have the SERIALIZABLE isolation level, then you will successfully fetch a.getB()
, even if that row was deleted in a concurrent transaction. If that row was already deleted and your transaction sees that, it means that either your DB is inconsistent (no foreign key) or that you used the wrong transaction isolation level.
Scenario 2: the entity a
is detached. When a LazyInitializationException
is thrown, that means to me that you called a.getB()
too late in order to guarantee a consistence in your application (as a
is not managed anymore). In order to solve the problem you simply call it earlier when the entity is still managed. A NPE cannot occur.
Why we need the DETACHED STATE? Well, we need a state in which the changes to an entity instance are not tracked. Why?
Example 1: suppose you receive an entity (with persistent identity) in the EJB layer and that there were no detached state (meaning all entities should be managed). But we need to do a validation before persisting the entity. If that entity would be automatically managed, its changes would be automatically persisted to DB. So this new state was introduced.
Example 2: you receive in the EJB layer an entity, any you need to update ONLY 5 fields of 10 from that entity. If that entity would get automatically into the managed state, all 10 fields would be persisted. The solution in this case is to fetch a managed entity and to update the 5 fields ONLY in that entity.
Detached - a detached instance is an object that has been persistent, but its Session has been closed. The reference to the object is still valid, of course, and the detached instance might even be modified in this state. A detached instance can be reattached to a new Session at a later point in time, making it (and all the modifications) persistent again. This feature enables a programming model for long running units of work that require user think-time. We call them application transactions, i.e., a unit of work from the point of view of the user.
References Hibernate DOc
Why?
The Session caches every object that is in a persistent state (watched and checked for dirty state by Hibernate). If you keep it open for a long time or simply load too much data, it will grow endlessly until you get an OutOfMemoryException. One solution is to call clear() and evict() to manage the Session cache,keeping a Session open for the duration of a user session also means a higher probability of stale data.
References Again Hibernate Doc
I bet you haven't read through hibernate documentation itself, It has scenarios explaining them too :)
Simple Explanation:With reference to persistent objects..
Suppose a user has to update a form, you get the details of user in from through UserObject, This user object is persistent with session. Now if user doesn't submit the form, your session is open until server session expires, how long will you wait? If you have used getCurrentSession, another form request comes while previous one is not submitted, you have got dirty data now!! What if your object is waiting for a data that is to come for a web-service and it taking long enough, will you still keep session open, object persistent with session?
Detached entities exists only to minimize the time your data is locked due to a transaction, maximizing the number of simultaneous users. Of course, this comes with a cost, and you listed them. but since merging conflicts are usually rare, people accept some rare bugs.
You see, data conflics will always exist, but they occur less when the transaction is short :-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With