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 11:20:18 -0400

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