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 Tue, 18 Dec 2007 16:39:51 GMT

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.


Mime
View raw message