You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@openjpa.apache.org by Kevin Sutter <kw...@gmail.com> on 2008/01/09 16:13:43 UTC

Re: merge only works with managed entity

Hi jackson12,
Back in the saddle again after an extended Christmas vacation...  :-)

Any progress on this request?  I took a quick look at your proposed patch
and although you indicated that it worked for your scenario, at least one of
our OpenJPA regression tests failed.  So, we can't just drop your patch into
OpenJPA.  But, we would like to understand the situation and maybe the patch
can be tweaked to get this resolved.  No promises...

In your last post, you indicated that you would create a small use case for
this scenario.  Any luck with that yet?  That would definitely help with
analyzing any proposed patches.  And, we would have a regression test for
this scenario.

Thanks,
Kevin

On Dec 18, 2007 10:39 AM, jackson12 <ke...@yahoo.com> wrote:

>
> I will create a small use case for this.
>
> thanks
>
> Patrick Linskey-2 wrote:
> >
> > Hi,
> >
> > Is it possible for you to post an example of the failure behavior? I'd
> > like to a) see why it's not Just Working, and b) have a regression
> > test in place if this fix does the trick.
> >
> > -Patrick
> >
> > On Dec 15, 2007 5:55 AM, jackson12 <ke...@yahoo.com> wrote:
> >>
> >> After making some small changes in OpenJPA source code, I am able to
> call
> >> a
> >> merge() method with an entity that's not detached. This allows our code
> >> that
> >> works in JBoss also work in IBM Websphere.
> >>
> >> Here is the change:
> >>
> >> in the attach method of class VersionAttachStrategy
> >> replace line 76:
> >>      boolean isNew = !broker.isDetached(pc);
> >> with:
> >>         Object id = getDetachedObjectId(manager, toAttach);
> >>         boolean isNew = true;
> >>         if (id != null)  isNew = false;
> >>
> >> Do you see any issues with this change?
> >>
> >> Thanks for the help!
> >>
> >>
> >>
> >>
> >> jackson12 wrote:
> >> >
> >> > 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 <ke...@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 <ke...@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 <ke...@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-tp14216438p14339820.html
> >>
> >> Sent from the OpenJPA Developers mailing list archive at Nabble.com.
> >>
> >>
> >
> >
> >
> > --
> > Patrick Linskey
> > 202 669 5907
> >
> >
>
> --
> View this message in context:
> http://www.nabble.com/merge-only-works-with-managed-entity-tp14216438p14400747.html
> Sent from the OpenJPA Developers mailing list archive at Nabble.com.
>
>

Re: merge only works with managed entity

Posted by Michael Dick <mi...@gmail.com>.
I've spoken with Jackson12 offline regarding the problem. I think the real
problem he's hitting is related to OPENJPA-245 :
http://issues.apache.org/jira/browse/OPENJPA-245.  The JIRA issue lists a
workaround by using the DetachedState annotation,

import org.apache.openjpa.persistence.DetachedState;

@Entity
@DetachedState(enabled=false)
public class Person {
    . . .
}

Unfortunately I found the workaround after I wrote a patch which also seems
to resolve the problem. I'll post the patch and other observations to the
JIRA shortly.

-Mike
On Jan 9, 2008 9:13 AM, Kevin Sutter <kw...@gmail.com> wrote:

> Hi jackson12,
> Back in the saddle again after an extended Christmas vacation...  :-)
>
> Any progress on this request?  I took a quick look at your proposed patch
> and although you indicated that it worked for your scenario, at least one
> of
> our OpenJPA regression tests failed.  So, we can't just drop your patch
> into
> OpenJPA.  But, we would like to understand the situation and maybe the
> patch
> can be tweaked to get this resolved.  No promises...
>
> In your last post, you indicated that you would create a small use case
> for
> this scenario.  Any luck with that yet?  That would definitely help with
> analyzing any proposed patches.  And, we would have a regression test for
> this scenario.
>
> Thanks,
> Kevin
>
> On Dec 18, 2007 10:39 AM, jackson12 <ke...@yahoo.com> wrote:
>
> >
> > I will create a small use case for this.
> >
> > thanks
> >
> > Patrick Linskey-2 wrote:
> > >
> > > Hi,
> > >
> > > Is it possible for you to post an example of the failure behavior? I'd
>
> > > like to a) see why it's not Just Working, and b) have a regression
> > > test in place if this fix does the trick.
> > >
> > > -Patrick
> > >
> > > On Dec 15, 2007 5:55 AM, jackson12 < kemin_chen@yahoo.com> wrote:
> > >>
> > >> After making some small changes in OpenJPA source code, I am able to
> > call
> > >> a
> > >> merge() method with an entity that's not detached. This allows our
> code
> > >> that
> > >> works in JBoss also work in IBM Websphere.
> > >>
> > >> Here is the change:
> > >>
> > >> in the attach method of class VersionAttachStrategy
> > >> replace line 76:
> > >>      boolean isNew = !broker.isDetached(pc);
> > >> with:
> > >>         Object id = getDetachedObjectId(manager, toAttach);
> > >>         boolean isNew = true;
> > >>         if (id != null)  isNew = false;
> > >>
> > >> Do you see any issues with this change?
> > >>
> > >> Thanks for the help!
> > >>
> > >>
> > >>
> > >>
> > >> jackson12 wrote:
> > >> >
> > >> > 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-tp14216438p14339820.html
> > >>
> > >> Sent from the OpenJPA Developers mailing list archive at Nabble.com.
> > >>
> > >>
> > >
> > >
> > >
> > > --
> > > Patrick Linskey
> > > 202 669 5907
> > >
> > >
> >
> > --
> > View this message in context:
> >
> http://www.nabble.com/merge-only-works-with-managed-entity-tp14216438p14400747.html
> > Sent from the OpenJPA Developers mailing list archive at Nabble.com.
> >
> >
>