openjpa-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Daryl Stultz <daryl.stu...@opentempo.com>
Subject Re: Evicting
Date Tue, 08 Feb 2011 17:32:07 GMT
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

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