openjpa-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Patrick Linskey" <plins...@gmail.com>
Subject Re: merge only works with managed entity
Date Sun, 16 Dec 2007 15:33:49 GMT
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

Mime
View raw message