openjpa-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Kevin Sutter" <kwsut...@gmail.com>
Subject Re: merge only works with managed entity
Date Tue, 11 Dec 2007 14:53:48 GMT
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.
>
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message