openjpa-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Craig L Russell <craig.russ...@oracle.com>
Subject Re: Evicting
Date Wed, 09 Feb 2011 00:49:11 GMT
Hi Daryl,

It appears to me that the issue you have is the conflation of entities  
(job1 and job2) with EntityManagers (the same entity manager is used  
by both job1 and job2 since you are using a thread local EM).

If you want job1 and job2 to stay isolated then each of them would  
need its own entity manager. And you would need to have some other  
mechanism (not thread local EM) to group related entities.

Or have I misunderstood your example below? The key for me is the "not  
logical"

> assertEquals("XX_newname_1", job1b.getName()); // !!! this is not  
> logical since I didn't "save" job1

Well, reading the code, both job1 and job2 share the same entity  
manager so "begin transaction, save, commit" will save changed  
instances.

You don't mention it, but I assume that setName immediately changes  
the state of a Role. So the "save" doesn't really do anything.

If you want to isolate changes to job1 and job2 you would have to  
buffer changes (e.g. setName) and only apply them when performing the  
save.

I also don't quite understand what you are trying to accomplish with:

> deleteViaJdbc(job1b);

Is this intended to simulate a third party deleting data that you're  
using? If so, then the observed behavior seems rational.

Craig


On Feb 8, 2011, at 9:32 AM, Daryl Stultz wrote:

> On Tue, Feb 8, 2011 at 11:08 AM, Michael Dick <michael.d.dick@gmail.com 
> >wrote:
>
>>> getting the deleted object out of L1. I thought that if the object  
>>> was
>>> modified prior to the JDBC delete, then another object was  
>>> modified and
>>> "saved", the save transaction would cause the deleted but dirty  
>>> object
>>> still
>>> in L1 to be saved as well (assuming it is still managed), but I  
>>> can't
>>> demonstrate this in a unit test.
>>>
>>
>> Haven't tried that scenario myself, and I'd be interested to hear  
>> what you
>> find out if you have time to try it.
>>
>> Here's a unit test that exposes what I consider a big problem with  
>> the JPA
> architecture:
>
> Role job1 = setup.insertJob("XX_1"); // instantiates and inserts via
> ThreadLocal EM
> Role job2 = setup.insertJob("XX_2");
> System.out.println("job1.getId() = " + job1.getId());
> System.out.println("job2.getId() = " + job2.getId());
> // both jobs "managed"
> job1.setName("XX_newname_1");
> job2.setName("XX_newname_2");
> // both dirty and managed
> job2.save(); // begin transaction, merge, commit
> setup.resetEntityManagerForNewTransaction(); // close previous EM,  
> open new
> one
> Role job1b = getEntityManager().find(Role.class, job1.getId());
> assertFalse(job1b == job1);
> assertEquals("XX_newname_1", job1b.getName()); // !!! this is not  
> logical
> since I didn't "save" job1
> Role job2b = getEntityManager().find(Role.class, job2.getId());
> assertFalse(job2b == job2);
> assertEquals("XX_newname_2", job2b.getName()); // this is expected
> // part two
> job1b.setName("XX_newname_1b"); // job1b dirty
> deleteViaJdbc(job1b);
> job2b.setName("XX_newname_2b"); // job2b dirty
> try {
> job2b.save();
> fail("Expected exception");
> } catch (OptimisticLockException exc) { // trying to update deleted  
> job
> exc.printStackTrace();
> }
> So I'm making changes to two objects, then saving just one of them.  
> The side
> effect is that both objects are saved. I repeat the process but  
> delete the
> changed object via JDBC. OpenJPA appears to be trying to save the  
> deleted
> object. Here's the output:
>
> job1.getId() = 170
> job2.getId() = 171
> <openjpa-1.2.2-r422266:898935 nonfatal store error>
> org.apache.openjpa.persistence.OptimisticLockException: An  
> optimistic lock
> violation was detected when flushing object instance
> "com.sixdegreessoftware.apps.rss.model.Role-170" to the data store.   
> This
> indicates that the object was concurrently modified in another  
> transaction.
> FailedObject: com.sixdegreessoftware.apps.rss.model.Role-170
>
> I don't think OpenJPA should be expected to handle my JDBC delete,  
> I'm just
> trying to illustrate why I called em.clear() after deleting via  
> JDBC. It
> would make the second problem go away but lead to lazy load  
> problems. The
> first problem marked with !!! is the "nature" of JPA I don't like  
> and I'm
> having to find a workaround for since I have to do the delete via  
> JDBC. At
> this point, I'm just hoping the "user" doesn't modify the object to be
> deleted.
>
> The main impact I foresee is that the other entities could have a  
> reference
>> to a deleted row. Resulting in a constraint violation
>> at runtime. Then again, you're running that risk so long as you  
>> have the
>> legacy cron job that deletes rows unless your code gets a callback.
>>
>
> There are certain things the "user" should not expect to do after  
> deleting
> an object, so if find() fails, that's OK. But the above scenario is  
> a little
> harder to understand. Why can't I change a property on an object,  
> delete it,
> then save some *other* object. I'm glazing over the problem of using  
> JDBC to
> do the delete, of course, but you see my point.
>
>
> -- 
> Daryl Stultz
> _____________________________________
> 6 Degrees Software and Consulting, Inc.
> http://www.6degrees.com
> http://www.opentempo.com
> mailto:daryl.stultz@opentempo.com

Craig L Russell
Architect, Oracle
http://db.apache.org/jdo
408 276-5638 mailto:Craig.Russell@oracle.com
P.S. A good JDO? O, Gasp!


Mime
View raw message