- Problem: This well-known managed state Update exception
Org.hibernate.nonuniqueobjectexception:a different object with the same identifier value is already associated withthe s Ession
- Previous occurrence scenario:
Almost every developer who has ever had a ormapping persistence program has encountered this exception.
This exception usually occurs within a session to generate multiple (often load (ID)/get (ID) one, and New+setid (ID) for the same database object, and then update it () or save ().
From the point of view of business logic, it often occurs in modified/updated operations.
- Previous causes of occurrence and means of resolution:
Often the session forget to close, or forget commit (), resulting in the two session should be divided into a session, this exception occurs.
The solution is also simple, separating the same operand from session level or transaction level through session shutdown and transaction. Between two operations Session.clear ();
- Now the new change in the problem:
- After hibernate3.0, getcurrentsession () technology, the advent of the session pool, the session no longer need to manually open, do not need to manually shut down, but complicate the problem
- The emergence of spring TransactionManager makes the problem more complicated
Various manger beans, the DAO bean opens the spring transaction management, and the spring transaction defines various operational isolation mechanisms, such as:
"A method under a transaction that calls another method, the other method no longer opens the transaction, but covers the transaction under the method that called it"
"A method under a transaction that calls another method, another method establishes a new transaction, the parent method's transaction is paused, and the other method executes before the transaction is resumed."
3. Some of the extended features represented by the STRUTS2 web framework make the problem more complex
typical example Struts2 Domain model. The JSP assigns a value directly to the property of the instance variable object of the action. If the instance attribute exists on the direct setter, if the instance attribute does not exist, the auto new instance
if this domain The model is an entity bean, which is more complicated if you set its ID through a JSP page, or have persisted it before.
4. If spring opensessioninviewfilter is present, to resolve lazyinitialization lazy load problem
Pass the session's cycle to the servlet filter to manage, and whenever request comes in, open a session,response end before closing it, so that the session can be present throughout the servlet request cycle
There are many techniques that have more or less the effect of the above 1-4 is the most typical.
- A different object with the same identifier value is already associated withthe session problem resolution:
In fact, I do not have a particularly good solution, the problem itself is a matter of opinion, the need for different scenarios different business logic to improvise. This article is only an exploration of the article, is open nature.
From my experience, I tend to solve the problem in two ways:
1. Session
From the point of view of the program, multiple analysis problems, find the beginning and end of the session.
But to tell the truth, this is really difficult, because now the code is more and more framework, modular, encapsulation is more and more deep, the session is not exposed to the business layer, the operation is often traced back to a very high level of the parent class, especially when and transaction hooks, it is more complex. And now the bottom of the session is increasingly obscure, based on the operation of the pool, based on the threadlocal operation, based on JTA.
2. From the update () aspect
At present, it is a more common view that using the merge () method to solve the problem is a "fool" solution.
Description of the Session.merge () method in JSR-220:
Copy the state of the given object onto the persistent object with the same identifier.
Copies the state, or instance properties, of a given object to a persisted object with the same ID
If There is no persistent instance currently associated with the session, it'll be loaded. Return the persistent instance.
If no persisted object is currently associated to the session, the current object is loaded as a persisted object, and the persisted object is returned (after the update)
If the given instance is unsaved, save a copy of and return it as a newly persistent instance. The given instance does not become associated with the session.
If the given instance has not been saved, a copy is stored and copy is returned as a new persisted object. The given object is no longer associated with the session
Simple summary:
Merge () will use the "Copy state copy", which is the direct method of property assignment, to complete the update of the same ID object, the actual is to clone the content of the past.
If it is a new object instance, merge () is actually equivalent to save () and persist ()
However, unlike save () and persist (), when merge () is complete, the object it operates on is the managed state.
A different object with the same identifier value is already associat