You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@openjpa.apache.org by Alessandro Ferrucci <al...@gmail.com> on 2007/07/14 22:43:39 UTC

weird behavior with entity updating

Yo guys,

I'm attempting to update an entity like so

manager.getTransaction().begin();
//attach entity to pers. context
//works fine
Obejct oldObj = doRead(newObj, manager);

//copy fields in newObj to oldObj
doMerge(oldObj,newObj);

//commit trans.
manager.getTransaction().commit();

here's the impl of doMerge, simple stuff...

 private void mergeAdapter(IJPAAdapter src, Object dest)
    {
        Field[] destFields = dest.getClass().getDeclaredFields();

        try
        {
            for (Field f : destFields)
            {
                if (!(f.isAnnotationPresent(Transient.class)))
                {
                    f.setAccessible(true);
                    f.set(dest, f.get(src));
                }
            }
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
            throw new RuntimeException(ex);
        }
    }

The fields get copied fine, however this changed entity never gets updated
in the data store.


however, if I create a copy method within my entity class which copies the
fields from the other object....this works fine.

I cannot figure out why the reflective solution wouldn't work but the second
would.  Any thoughts?

thx a bunch

--
alessandro ferucci =]

Re: weird behavior with entity updating

Posted by Alessandro Ferrucci <al...@gmail.com>.
The issue with merge is this:

here's the scenario with merge:

//read the old object
Object old = doRead(adapter, manager);

//merge new object into persistence context and persist

manager.getTransaction().begin();
Object r = manager.merge(adapter);
manager.getTransaction().commit();

I do a query to get the old object out of data store.  In my entity class
I've defined an IdClass, whereby Merge will be able to tell which entity to
find in the persistence context to merge INTO.  After the read the "old"
object is attached to my perssitence context, so then I begin a transaction,
merge my new object in (merge should be using my idClass to find which
object to overwrite in the persitence context) and commit the transaction,
at this point any fields which have changed in my "adapter" object should be
changed in the datastore.  When I try to run this code openJPA screams that
I cannot persist the new object because one of the same id already exists in
the context:

<2|false|0.9.6-incubating>
org.apache.openjpa.persistence.EntityExistsException: An object of type "
com.aol.pubt.sports.cbk.adapter.db.CbkPollBeanAdapter" with oid "
com.aol.pubt.sports.cbk.adapter.db.CbkPollBeanAdapter-com.aol.pubt.sports.cbk.adapter.db.CbkPollBeanAdapter$CompId@c4a7c34"
already exists in this context; another cannot be persisted.
FailedObject: com.aol.pubt.sports.cbk.adapter.db.CbkPollBeanAdapter@ceed49
        at org.apache.openjpa.kernel.BrokerImpl.persist(BrokerImpl.java
:2359)
        at org.apache.openjpa.kernel.AttachStrategy.persist(
AttachStrategy.java:91)
        at org.apache.openjpa.kernel.VersionAttachStrategy.attach(
VersionAttachStrategy.java:85)
        at org.apache.openjpa.kernel.AttachManager.attach(AttachManager.java
:236)
        at org.apache.openjpa.kernel.AttachManager.attach(AttachManager.java
:97)
        at org.apache.openjpa.kernel.BrokerImpl.attach(BrokerImpl.java:3124)

So what it tells me here is that Merge did not at all try to "merge" the new
values in my "adapter" into the values of my "old" in my persistence
context, instead it just tried to do a simple attach of my "adapter" object
and because both "old" and "adapater" have the same Id defined it failed, so
that's why I was trying to do the merge manually.


thx

alessandro ferrucci =]


On 7/16/07, Patrick Linskey <pl...@gmail.com> wrote:
>
> OpenJPA does not detect changes made via reflection; you need to call
> OpenJPAEntityManager.dirty(o, "fieldName") to tell OpenJPA that they
> changed. This is because the bookkeeping cost of attempting to scan all
> instances that were loaded in a transaction can quickly become
> prohibitively
> expensive.
>
> Also, why are you doing the copy? EntityManager.merge() should take care
> of
> copying old values onto the managed instance automatically.
>
> -Patrick
>
> On 7/14/07, Alessandro Ferrucci <al...@gmail.com> wrote:
> >
> > Yo guys,
> >
> > I'm attempting to update an entity like so
> >
> > manager.getTransaction().begin();
> > //attach entity to pers. context
> > //works fine
> > Obejct oldObj = doRead(newObj, manager);
> >
> > //copy fields in newObj to oldObj
> > doMerge(oldObj,newObj);
> >
> > //commit trans.
> > manager.getTransaction().commit();
> >
> > here's the impl of doMerge, simple stuff...
> >
> > private void mergeAdapter(IJPAAdapter src, Object dest)
> >     {
> >         Field[] destFields = dest.getClass().getDeclaredFields();
> >
> >         try
> >         {
> >             for (Field f : destFields)
> >             {
> >                 if (!(f.isAnnotationPresent(Transient.class)))
> >                 {
> >                     f.setAccessible(true);
> >                     f.set(dest, f.get(src));
> >                 }
> >             }
> >         }
> >         catch (Exception ex)
> >         {
> >             ex.printStackTrace();
> >             throw new RuntimeException(ex);
> >         }
> >     }
> >
> > The fields get copied fine, however this changed entity never gets
> updated
> > in the data store.
> >
> >
> > however, if I create a copy method within my entity class which copies
> the
> > fields from the other object....this works fine.
> >
> > I cannot figure out why the reflective solution wouldn't work but the
> > second
> > would.  Any thoughts?
> >
> > thx a bunch
> >
> > --
> > alessandro ferucci =]
> >
>
>
>
> --
> Patrick Linskey
> 202 669 5907
>

Re: weird behavior with entity updating

Posted by Patrick Linskey <pl...@gmail.com>.
OpenJPA does not detect changes made via reflection; you need to call
OpenJPAEntityManager.dirty(o, "fieldName") to tell OpenJPA that they
changed. This is because the bookkeeping cost of attempting to scan all
instances that were loaded in a transaction can quickly become prohibitively
expensive.

Also, why are you doing the copy? EntityManager.merge() should take care of
copying old values onto the managed instance automatically.

-Patrick

On 7/14/07, Alessandro Ferrucci <al...@gmail.com> wrote:
>
> Yo guys,
>
> I'm attempting to update an entity like so
>
> manager.getTransaction().begin();
> //attach entity to pers. context
> //works fine
> Obejct oldObj = doRead(newObj, manager);
>
> //copy fields in newObj to oldObj
> doMerge(oldObj,newObj);
>
> //commit trans.
> manager.getTransaction().commit();
>
> here's the impl of doMerge, simple stuff...
>
> private void mergeAdapter(IJPAAdapter src, Object dest)
>     {
>         Field[] destFields = dest.getClass().getDeclaredFields();
>
>         try
>         {
>             for (Field f : destFields)
>             {
>                 if (!(f.isAnnotationPresent(Transient.class)))
>                 {
>                     f.setAccessible(true);
>                     f.set(dest, f.get(src));
>                 }
>             }
>         }
>         catch (Exception ex)
>         {
>             ex.printStackTrace();
>             throw new RuntimeException(ex);
>         }
>     }
>
> The fields get copied fine, however this changed entity never gets updated
> in the data store.
>
>
> however, if I create a copy method within my entity class which copies the
> fields from the other object....this works fine.
>
> I cannot figure out why the reflective solution wouldn't work but the
> second
> would.  Any thoughts?
>
> thx a bunch
>
> --
> alessandro ferucci =]
>



-- 
Patrick Linskey
202 669 5907