openjpa-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jackson12 <kemin_c...@yahoo.com>
Subject Re: merge only works with managed entity
Date Fri, 14 Dec 2007 13:56:11 GMT

Kevin, Patrick,

Any update on this?

We want to quickly decide if we can switch to OpenJPA with IBM Websphere,
this is currently our show stopper.



jackson12 wrote:
> 
> Kevin,
> 
> What you described is exactly the problem. 
> 
> But unfortunately we don't have the luxury to use the approach you
> proposed (find-->detach-->merge)
> because our application is a struts based web application, and on the web
> tier we have a different set of DTOs to hold the changes from end user and
> currently we are only migrating our backend to use EJB3.
> 
> so at someplaces, we have to copy the values from DTO to managed or
> detached entities, but I don't know any "smarter copy" that can also
> maintain the extra code in the managed or detached entity.
> 
> This should be a very common scenarios. Please let me know if you or
> Patrick have some other ideas. 
> 
> Thanks in advance!
> 
> 
> 
> Kevin Sutter wrote:
>> 
>> jackson12,
>> I understand your problem.  Since the Person object holds a nested
>> Address
>> object, when you use the copyProperties() method, the nested managed
>> Address
>> object gets overwritten with an unmanaged instance.  Right?
>> 
>> The copyProperties() method is kind of simple.  It just copies attribute
>> by
>> attribute.  Since it sees an Address attribute, it just copies the new
>> Address attribute right on top of the managed one.  The problem here is
>> that
>> the managed instance of Address has OpenJPA state associated with it. 
>> When
>> the copyProperties() is invoked, we lose all of that state data (and
>> code)
>> due to the unmanaged Address object.  Hibernate's method of keeping track
>> of
>> object state must be different from the way that OpenJPA does it.
>> 
>> What it sounds like you need is a smarter copyProperties() method.  One
>> that
>> will copy the simple property values, but then traverse into the nested
>> managed objects to do it's own copyProperties().  But, then if these
>> nested
>> objects have additional nested managed objects, you run into the same
>> complication.
>> 
>> How about using the merge() operation to accomplish this task?  Instead
>> of
>> just creating new unmanaged instances of your Person objects, do a find
>> operation to get them managed by your persistence context.  Then, detach
>> the
>> entities and do whatever updates you want to these detached instances. 
>> When
>> you are ready to copy them back in to the persistence context, call the
>> merge() method and let the changes merge back into the persistence
>> context.
>> This would seem to be along the lines of processing that you are looking
>> for, but from a different angle.
>> 
>> I'll copy Patrick on this reply just to see if he has some other ideas.
>> 
>> Thanks,
>> Kevin
>> 
>> 
>> On Dec 11, 2007 8:02 AM, jackson12 <kemin_chen@yahoo.com> wrote:
>> 
>>>
>>> Kevin,
>>>
>>> Thanks again for the clarification.
>>>
>>> Here is the scenario for the nested properties.
>>>
>>> Suppose I have an entity Person that holds a nested entity Address.
>>> Assume
>>> I
>>> use find() method to load
>>> the Person entity with Address. Now in order to apply the changes, we
>>> normally use
>>>
>>>     PropertyUtils.copyProperties(managedPerson, inputPerson);
>>>
>>> or
>>>    BeanUtils.copyProperties(managedPerson, inputPerson);
>>>
>>> but these copyProperties method will make the nested Address entity
>>> non-managed (because the Address reference will be replaced by , and
>>> hence
>>> OpenJPA will throw exception when I call the merge() method later. In
>>> order
>>> to bypass this, we have to copy field by field from inputPerson to
>>> managedPerson including the nested entity. This makes the code very
>>> error
>>> prone and ugly.
>>>
>>> JBoss's implementation does not require the inputPerson to be managed or
>>> detached, I know this maybe beyond JPA1.0 spec, but it is really very
>>> helpful.
>>>
>>> Do I misunderstand anything?
>>>
>>> thanks a lot
>>>
>>>
>>>
>>> Kevin Sutter wrote:
>>> >
>>> > jackson12,
>>> > If I am understanding your scenario correctly, your userProfile input
>>> > parameter is an unmanaged entity, but the key for this entity does
>>> already
>>> > exist in the database.  So, when you attempt to do the merge()
>>> processing
>>> > (and subsequent transaction commit), you are getting a "duplicate key"
>>> > exception from Oracle.
>>> >
>>> > Calling merge() with a new unmanaged entity acts like a persist() call
>>> and
>>> > adds it to the persistence context.  The persist() method is intended
>>> for
>>> > new entities that do not currently exist in the database.
>>> >
>>> > So, on the surface, your scenario seems to be acting as I would expect
>>> > with
>>> > any JPA implementation.  But, you have indicated that JBoss' Hibernate
>>> is
>>> > processing as you had hoped.  Based on my understanding of the spec
>>> and
>>> > your
>>> > scenario, I think you are getting lucky with Hibernate.
>>> >
>>> > I would suggest doing the find() operation first to properly load the
>>> > entity
>>> > into the persistence context and then do your updates.  You can always
>>> > detach this entity from the persistence context, if necessary, for
>>> other
>>> > processing and then merge it back in later.  Since the merge() would
>>> be
>>> > operating on a known, detached entity, an update operation will be
>>> > performed
>>> > instead of the insert.
>>> >
>>> > A few other observations...  Remember that the merge() operation
>>> returns
>>> > the
>>> > managed entity as a return value.  The original entity that you passed
>>> > into
>>> > the merge() method is not managed.  So, if you want any state changes
>>> to
>>> > the
>>> > entity to be properly maintained and persisted, you need to use the
>>> > returned
>>> > managed instance of the entity from the merge() operation.
>>> >
>>> > You also mentioned how the nested properties are not managed.  This
>>> may
>>> be
>>> > related to the above observation.  Another possibility is that you
>>> need
>>> to
>>> > declare whether you want the merge processing to be cascaded to the
>>> > objects
>>> > pointed to by the entity.  You would specify this on the relationship
>>> > annotation via the cascade=CascadeType.MERGE element.  You haven't
>>> > provided
>>> > the complete entity definition, so I'm not exactly sure how you have
>>> these
>>> > entity types defined.
>>> >
>>> > Hope this information helps.
>>> >
>>> > Good luck,
>>> > Kevin
>>> >
>>> > On Dec 7, 2007 11:50 AM, jackson12 <kemin_chen@yahoo.com> wrote:
>>> >
>>> >>
>>> >> Thanks Kevin for your prompt response.
>>> >> Here is a simple use case we have:
>>> >> within an EJB , we have the following method:
>>> >>
>>> >> public UserProfile updateUserProfile(UserProfile userProfile) {
>>> >>                return getProfileDAO().update(userProfile);
>>> >> }
>>> >>
>>> >> when this method is called, the input parameter has all of the values
>>> >> including the key, but we got a runtime exception because it's trying
>>> to
>>> >> insert userProfile into database.
>>> >>
>>> >> org.apache.openjpa.persistence.PersistenceException: ORA-00001:
>>> unique
>>> >> constraint (VPDNGDITR17.PK_SECURITY_USER_PROFILE) violated
>>> FailedObject:
>>> >> prepstmnt 1645109774 INSERT INTO SECURITY_USER_PROFILE (OID,
>>> >> MODIFIED_BY_USER, ........
>>> >>
>>> >> After we change the code to the following, it works fine:
>>> >>        public UserProfile updateUserProfile(UserProfile userProfile)
>>> {
>>> >>                UserProfileDAO profileDAO = getProfileDao();
>>> >>                UserProfile tmpUserProfile =
>>> >> profileDAO.getUserProfile(userProfile.getName());
>>> >>                PropertyUtils.copyProperties(tmpUserProfile,
>>> userProfile);
>>> >>                return getProfileDao().update(tmpUserProfile);
>>> >>        }
>>> >>
>>> >> Here is the update method of ProfileDAO:
>>> >>
>>> >> public T update(T entity)
>>> >> {
>>> >>       getEntityManager().merge(entity);
>>> >> }
>>> >>
>>> >> When the input parameter has nested object, even the above approach
>>> won't
>>> >> work any more, because PropertyUtils.copyProperties will make the
>>> nested
>>> >> object not managed anymore.
>>> >>
>>> >> Thanks a lot
>>> >>
>>> >>
>>> >> Kevin Sutter wrote:
>>> >> >
>>> >> > jackson12,
>>> >> > Could you be more specific with your example?  We have various
>>> >> testcases
>>> >> > that do this exact process of merging in non-managed entities
>>> (without
>>> >> > first
>>> >> > retrieving the entity from the DB).   Could you further explain
>>> your
>>> >> test
>>> >> > scenario and what results you are getting?
>>> >> >
>>> >> > Thanks,
>>> >> > Kevin
>>> >> >
>>> >> > On Dec 7, 2007 11:12 AM, jackson12 <kemin_chen@yahoo.com>
wrote:
>>> >> >
>>> >> >>
>>> >> >> Hi, We are trying to migrate our JBoss EJB3 application to
IBM
>>> >> websphere
>>> >> >> with
>>> >> >> OpenJPA. We noticed in OpenJPA, the merge method does not work
>>> with
>>> >> >> non-managed entity. You have to retrieve the entity from DB,
make
>>> some
>>> >> >> changes and then call merge. But with JBoss's implementation,
you
>>> >> don't
>>> >> >> have
>>> >> >> to retrieve the entity from DB first. the merge method works
fine
>>> for
>>> >> >> non-managed entity.
>>> >> >>
>>> >> >> Is there anyway for OpenJPA to work the same way as JBoss's
JPA
>>> >> >> implementation on this part? or is there a way in OpenJPA to
make
>>> a
>>> >> >> non-managed entity managed?
>>> >> >>
>>> >> >> thanks in advance
>>> >> >> --
>>> >> >> View this message in context:
>>> >> >>
>>> >>
>>> http://www.nabble.com/merge-only-works-with-managed-entity-tf4963245.html#a14216438
>>> >> >> Sent from the OpenJPA Developers mailing list archive at
>>> Nabble.com.
>>> >> >>
>>> >> >>
>>> >> >
>>> >> >
>>> >>
>>> >> --
>>> >> View this message in context:
>>> >>
>>> http://www.nabble.com/merge-only-works-with-managed-entity-tf4963245.html#a14217307
>>> >> Sent from the OpenJPA Developers mailing list archive at Nabble.com.
>>> >>
>>> >>
>>> >
>>> >
>>>
>>> --
>>> View this message in context:
>>> http://www.nabble.com/merge-only-works-with-managed-entity-tp14216438p14274498.html
>>> Sent from the OpenJPA Developers mailing list archive at Nabble.com.
>>>
>>>
>> 
>> 
> 
> 

-- 
View this message in context: http://www.nabble.com/merge-only-works-with-managed-entity-tp14216438p14336208.html
Sent from the OpenJPA Developers mailing list archive at Nabble.com.


Mime
View raw message