Thanks for looking at this Mike, The main question/concern I have is concurrency...
Imagine simultaneous users hitting a web-app. A call to merge in one users request, does that save changes to an entity that another user's request is editing? Right now, I take my JPA entities and I expose them to my (struts) views and when the user submits a form, getters/setters get called on the (potentially managed) entities. The action may or may not save the changes, but if another user's request leads to a merge call, then would that lead to changes being saved on all entities managed by the entity manager? I will spend some time looking through the docs and the spec, but if anyone follows a similar use-case, I'd like to know how they handle this... Should I detach the entities after retrieving them? Should I copy the properties of the entities into a transfer object? In addition, if changes to all managed entities are saved when an entity is merged, then what is the point of having cascade configurations? A quick re-read of your email, and I want to be clear that you understood that unit test. The merge call is a different entity than the one that is tested... The pseudo-code of the unit test is this - retrieve EntityA retrieve EntityB change EntityA.someProp change EntityB.someProp save Entity*A* (through merge call) retrieve a new copy of Entity*B* check EntityB.someProp matches what it used to be (since EntityB was never explicitly saved) If you were addressing it correctly, I apologize for reiterating. -Wes On Tue, Apr 27, 2010 at 9:54 AM, Michael Dick <[email protected]> wrote: > Hi Wes, > > Thanks for putting the example on pastebin, it's much easier to read the > code there than in an email. > > The test should not pass, the row should be updated in the database when you > commit the transaction. You've obtained an instance of your entity and > modified it's contents. The entity is managed at this point, meaning that > JPA is tracking the changes you make, and those changes will be updated in > the database when the transaction commits. > > Even if the entity was not managed (for example if you called em.clear() > before updating it), the merge operation would take any changes and copy > them into a new managed instance of the entity. The contents of that managed > entity would be updated in the database when the transaction commits. > > There's more information in the JPA spec itself (look for managed entities) > or in the OpenJPA manual > http://openjpa.apache.org/builds/latest/docs/manual/manual.html#jpa_overview_em_lifeexamples > (example > 8.2 hits your case fairly closely). > > hth > -mike > > On Tue, Apr 27, 2010 at 8:11 AM, Wes Wannemacher <[email protected]> wrote: > >> bump... >> >> I think the first time I posted this message, pastebin went offline, >> but the unit test is back up and visible... >> >> http://pastebin.com/kDw1rX7e >> >> What I'd really like to know is whether this test should ever pass, >> and if not, where can I read about the details of the merge call. If >> it should pass, that would be interesting as well because I would know >> to go take it up with the Spring folks. >> >> -Wes >> >> On Fri, Apr 23, 2010 at 1:57 PM, Wes Wannemacher <[email protected]> wrote: >> > Hello, I've been lurking on this list for a while and i have been a >> > happy user for OpenJPA for a year or so. However, I came across a >> > situation recently which kind of suprised me. >> > >> > Imagine that both CDO_ConditionCode and CDO_CageCode are enhanced >> > entities that do not a relationship. These beans have an @Id field (of >> > type String) and a description (of type String). Here is the >> > interesting snippet of a unit test I wrote to check out this behavior >> > -> >> > >> > CDO_ConditionCode retrievedCondCode = em.find(CDO_ConditionCode.class, >> "00"); >> > CDO_CageCode retrievedCageCode = em.find(CDO_CageCode.class, "00000"); >> > >> > retrievedCondCode.setDescription("new description"); >> > retrievedCageCode.setDescription("new description"); >> > >> > em.getTransaction().begin(); >> > retrievedCageCode = em.merge(retrievedCageCode); >> > // em.flush(); // with or without the flush, this test fails >> > em.getTransaction().commit(); >> > >> > CDO_ConditionCode otherRetrievedCondCode = >> > em.find(CDO_ConditionCode.class, "00"); >> > assertTrue("expected value not to change", "description of >> > 00".equals(otherRetrievedCondCode.getDescription())); >> > >> > I noticed it while working on an oracle database. I had a breakpoint >> > in one section of my code and I was trying to figure out an unrelated >> > problem. While the app was hanging at the breakpoint, I noticed that >> > changes to an unmerged entity had been written to the database. If you >> > want to see the full unit test, it will be available here for a little >> > while - >> > >> > http://pastebin.com/kDw1rX7e >> > >> > In the application, most of the JPA operations are hidden behind a DAO >> > that delegates to Spring's JpaTemplate. However, I wrote the unit test >> > to get rid of the JpaTemplate to see if hte problem was with my DAO, >> > Spring or OpenJPA. In addition to removing the JpaTemplate, I also ran >> > the unit test using EclipseLink 2.0.2, which failed at the assert, >> > just like OpenJPA. That leads me to believe that this isn't >> > necessarily a *problem*, but it is that maybe I misunderstand the >> > behavior of a call to merge. Can someone explain to me why this fails, >> > or just point me to a section that would help me understand why a >> > merge to one entity causes the other entity to be saved to the >> > database. Or, if this should succeed, I will look further at Spring >> > being the culprit (even though I eliminated the JpaTemplate, I did not >> > eliminate Spring's LocalContainerEntityManagerFactoryBean). >> > >> > Thanks guys! >> > >> > -Wes >> > >> > -- >> > Wes Wannemacher >> > >> > Head Engineer, WanTii, Inc. >> > Need Training? Struts, Spring, Maven, Tomcat... >> > Ask me for a quote! >> > >> >> >> >> -- >> Wes Wannemacher >> >> Head Engineer, WanTii, Inc. >> Need Training? Struts, Spring, Maven, Tomcat... >> Ask me for a quote! >> > -- Wes Wannemacher Head Engineer, WanTii, Inc. Need Training? Struts, Spring, Maven, Tomcat... Ask me for a quote!
