persistence@glassfish.java.net

RE: Re: Trying to add new child entity; getting OptimisticLockException

From: Gordon Yorke <gordon.yorke_at_oracle.com>
Date: Fri, 29 Sep 2006 14:04:53 -0400

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
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>
>>>>
>
>
>