persistence@glassfish.java.net

Re: Trying to add new child entity; getting OptimisticLockException

From: Ellen Kraffmiller <ekraffmiller_at_hmdc.harvard.edu>
Date: Fri, 29 Sep 2006 14:40:20 -0400

Hi Gordon,
All the primary keys are generated, so I don't think that's the cause of
our error.
Also, even if we were not getting an Optimistic lock exception, I don't
see how to avoid clearing out the collection in the managed entity, and
recreating it. I don't know how else to handle the scenario where
elements were removed from the collection while the entity was detached.
Thanks,
Ellen

Gordon Yorke wrote:

>Hello Ellen
> What is the primary key value for FileCategories? Are they natural PK's or generated? If they are not generated the issue you are seeing that you are creating a new FileCategory with the same PK as an existing object. Because the new FileCategory has no version TopLink throws an Optimistic lock exception. You will need to find the pre-existing FileCategory's that correspond to the newly created FileCategory and add them to the Study object.
> As an alternative you could also change your cascade setting to not cascade .
>--Gordon
>
>-----Original Message-----
>From: Ellen Kraffmiller [mailto:ekraffmiller_at_hmdc.harvard.edu]
>Sent: Friday, September 29, 2006 11:20 AM
>To: persistence_at_glassfish.dev.java.net
>Subject: Re: Trying to add new child entity; getting
>OptimisticLockException
>
>
>Hi,
>After doing some testing, I've found a way to update the dependent
>collection from the detached study that works:
>
> public void updateStudy(Study detachedStudy){
> Study managedStudy = em.find(Study.class,detachedStudy.getId());
>
> // Remove existing collections on managed study
> for (Iterator<FileCategory> it =
>managedStudy.getFileCategories().iterator(); it.hasNext();) {
> FileCategory elem = it.next();
> em.remove(elem);
> }
> managedStudy.getFileCategories().clear();
>
> // Add the collection from the detached study
> //(need to create new FileCategory objects, if we don't we get a
>"trying to persist a detched object" exception)
>
> for (Iterator<FileCategory> it =
>detachedStudy.getFileCategories().iterator(); it.hasNext();) {
> FileCategory elem = it.next();
> FileCategory fileCategory = new FileCategory();
> fileCategory.setOtherId(elem.getOtherId());
> fileCategory.setAgency(elem.getAgency());
> fileCategory.setStudy(managedStudy);
> managedStudy.getFileCategories().add(fileCategory);
> }
>
>This seems like an awful lot of code to do a relatively straightforward
>update. Is this the recommended approach?
>The only way I see to avoid this is to us Stateful Session bean with an
>extended persistence context. Is that how most people handle this?
>Thanks,
>Ellen
>
>
>gdurand_at_hmdc.harvard.edu wrote:
>
>
>
>>We are prefetching relationships. We prefer to do it that way because
>>sometimes we don't need to get them.
>>
>>
>>Quoting Marina Vatkina <Marina.Vatkina_at_Sun.COM>:
>>
>>
>>
>>>Ellen,
>>>
>>>Are you adding a file category to a study before passing it back?
>>>Is 'fileCategories' marked as FetchType.EAGER when you pass a
>>>study to the client (ToMany relationship defaults to LAZY fetching),
>>>or do you prefetch the relationships? If not, does it make a difference
>>>if you do?
>>>
>>>thanks,
>>>-marina
>>>
>>>Ellen Kraffmiller wrote:
>>>
>>>
>>>
>>>>Thanks Marina, please see my comments
>>>>-Ellen
>>>>
>>>>Marina Vatkina wrote:
>>>>
>>>>
>>>>
>>>>>Ellen,
>>>>>
>>>>>Ellen Kraffmiller wrote:
>>>>>
>>>>>
>>>>>
>>>>>>Hi Gordon & Marina,
>>>>>>After doing more testing, the problem seems to be related to
>>>>>>using a detached entity. In our original example, the study
>>>>>>object we are merging was previously detached and sent to the web
>>>>>> tier. I tried the same logic with a Study entity that is
>>>>>>managed, and it works.
>>>>>>
>>>>>>So, to summarize, this works:
>>>>>>doUpdate(Long id) {
>>>>>> Study study = em.find(Study.class, id);
>>>>>> FileCategory c = new FileCategory();
>>>>>> c.setName( "test" );
>>>>>> c.setStudy(study);
>>>>>> study.getFileCategories().add(c);
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>>You do not need to merge a managed instance, assuming you have cascade
>>>>>PERSIST or ALL set:
>>>>>
>>>>>
>>>>>
>>>>>> em.merge(study);
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>>
>>>>Right, I forgot about that when I was doing the test.
>>>>
>>>>
>>>>
>>>>>>}
>>>>>>
>>>>>>But the following throws an Opimistic Lock Exception:
>>>>>>(No modifications to the fileCategories collection were made
>>>>>>while the study was detached.)
>>>>>>
>>>>>>doUpdate(Study detachedStudy) {
>>>>>> FileCategory c = new FileCategory();
>>>>>> c.setName( "test" );
>>>>>> c.setStudy(study);
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>>Do you mean 'detachedStudy'?
>>>>>
>>>>>
>>>>
>>>>Yes, that was a typo.
>>>>
>>>>
>>>>
>>>>>> study.getFileCategories().add(c);
>>>>>> em.merge(study);
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>>Does the opposite works (with appropriate cascade settings)?
>>>>>
>>>>> em.merge(study);
>>>>>
>>>>> FileCategory c = new FileCategory();
>>>>> c.setName( "test" );
>>>>> c.setStudy(study);
>>>>> study.getFileCategories().add(c);
>>>>>
>>>>>
>>>>>
>>>>>
>>>>This may work, but it doesn't really fit our requirements. Our
>>>>example is simplified to show what is happening in one code
>>>>snippet. Just to give you a background on what we are doing, we are
>>>> implementing a standard web application with forms for updating a
>>>>Study and all its related data. So, in this case, we are getting a
>>>> Study entitiy from the database, presenting a form to the user
>>>>where he can update the file categories for the Study (as well as
>>>>other dependent entities), then calling a session bean method that
>>>> attempts to merge the Study to the database. We can't add the
>>>>fileCategory object after merging the study, because the study
>>>>being passed to the session bean already has all the file category
>>>>data (and other dependent collections) set.
>>>>
>>>>
>>>>
>>>>>thanks,
>>>>>-marina
>>>>>
>>>>>
>>>>>
>>>>>>}
>>>>>>
>>>>>>Is something we need to be doing differently to merge the detached
>>>>>>study?
>>>>>>
>>>>>>Thanks,
>>>>>>Ellen
>>>>>>
>>>>>>Marina Vatkina wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>>>Gordon,
>>>>>>>
>>>>>>>Is there a way to check which exactly PK causes this error?
>>>>>>>Can it be that there is another FileCategory instance that
>>>>>>>is the problem?
>>>>>>>
>>>>>>>thanks,
>>>>>>>-marina
>>>>>>>
>>>>>>>Gordon Yorke wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>>Nothing jumps out as an issue, if you are not on the latest
>>>>>>>>version of TopLink Essentials I would recommend updating your
>>>>>>>>TopLink Essentials jar and if the problem persists file a
>>>>>>>>glassfish issue with testcase.
>>>>>>>>--Gordon
>>>>>>>>
>>>>>>>>-----Original Message-----
>>>>>>>>From: Ellen Kraffmiller [mailto:ekraffmiller_at_hmdc.harvard.edu]
>>>>>>>>Sent: Thursday, September 28, 2006 11:24 AM
>>>>>>>>To: persistence_at_glassfish.dev.java.net
>>>>>>>>Subject: Re: Trting to add new child entity; getting
>>>>>>>>OptimisticLockException
>>>>>>>>
>>>>>>>>
>>>>>>>>The version is being left as null - we are never setting it.
>>>>>>>>Thanks,
>>>>>>>>Ellen
>>>>>>>>
>>>>>>>>Gordon Yorke wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>>Hello Ellen,
>>>>>>>>>In the constrctor of FileCategory is version being initialized
>>>>>>>>> to new Long(X) or being left as null?
>>>>>>>>>--Gordon
>>>>>>>>>
>>>>>>>>>-----Original Message-----
>>>>>>>>>From: Ellen Kraffmiller [mailto:ekraffmiller_at_hmdc.harvard.edu]
>>>>>>>>>Sent: Thursday, September 28, 2006 10:27 AM
>>>>>>>>>To: persistence_at_glassfish.dev.java.net
>>>>>>>>>Subject: Re: Trting to add new child entity; getting
>>>>>>>>>OptimisticLockException
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>Hi Gordon,
>>>>>>>>>I am working with Gustavo on this problem so I thought I'd
>>>>>>>>>answer your
>>>>>>>>>questions. The version field is defined as:
>>>>>>>>>
>>>>>>>>>@Version
>>>>>>>>> private Long version;
>>>>>>>>>(with normal getters and setters)
>>>>>>>>>
>>>>>>>>>We are using SostgreSQL, and the database column is version, int8.
>>>>>>>>>
>>>>>>>>>Thanks,
>>>>>>>>>Ellen
>>>>>>>>>
>>>>>>>>>Gordon Yorke wrote:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>>Hello Gustavo,
>>>>>>>>>>What is the version field in FileCategory being initialized
>>>>>>>>>>to? What type is the version field?
>>>>>>>>>>--Gordon
>>>>>>>>>>
>>>>>>>>>>-----Original Message-----
>>>>>>>>>>From: gdurand_at_hmdc.harvard.edu [mailto:gdurand_at_hmdc.harvard.edu]
>>>>>>>>>>Sent: Wednesday, September 27, 2006 5:57 PM
>>>>>>>>>>To: persistence_at_glassfish.dev.java.net
>>>>>>>>>>Subject: Trting to add new child entity; getting
>>>>>>>>>>OptimisticLockException
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>Hi,
>>>>>>>>>>
>>>>>>>>>>I'm am trying a very simple example and am getting a problem
>>>>>>>>>>(I am using glassfish v2 milestone 1):
>>>>>>>>>>
>>>>>>>>>>Our DB has a Study entity which has a one to many relationship
>>>>>>>>>>with a FileCategory entity.
>>>>>>>>>>
>>>>>>>>>>When I try to add a FileCategory to an existing study:
>>>>>>>>>>
>>>>>>>>>> Collection categories = study.getFileCategories();
>>>>>>>>>>
>>>>>>>>>> FileCategory c = new FileCategory();
>>>>>>>>>> c.setName( "test" );
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> c.setStudy(study);
>>>>>>>>>> categories.add(c);
>>>>>>>>>>
>>>>>>>>>> em.merge(study);
>>>>>>>>>>
>>>>>>>>>>I am getting:
>>>>>>>>>>
>>>>>>>>>>Exception Details:
>>>>>>>>>>oracle.toplink.essentials.exceptions.OptimisticLockException
>>>>>>>>>>Exception Description: The object
>>>>>>>>>>[edu.harvard.hmdc.vdcnet.study.FileCategory_at_1f1c748] cannot be
>>>>>>>>>>merged
>>>>>>>>>>because it has changed or been deleted since it was last read.
>>>>>>>>>>{3}Class> edu.harvard.hmdc.vdcnet.study.FileCategory
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>Any ideas why this is happening, since the FileCategory
>>>>>>>>>>doesn't exist
>>>>>>>>>>in the first place? (I have seen an example in the O'Reilly
>>>>>>>>>>book that
>>>>>>>>>>pretty much does just this)?
>>>>>>>>>>
>>>>>>>>>>Thanks,
>>>>>>>>>>Gustavo
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>
>>
>>
>
>
>