openjpa-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "LYALIKOV, Oleg (Oleg)" <oleg.lyali...@alcatel-lucent.com>
Subject RE: Incorrect concurrent persist of ManyToOne field
Date Mon, 09 Dec 2013 20:36:53 GMT
Okay, that explains the issue. And also I suppose it can be hard to somehow detect such situation
in OpenJPA...
Do you think it can be possible to employ some fail-fast check or something in that case?
Just a bit frustrated of time spent finding the issue (not so much experience in concurrency
+ real case was a bit more complicated) and wondering if someone else can run against such
issue (or me again :)

Nevertheless, big thanks for help and explanation
Oleg

-----Original Message-----
From: Rick Curtis [mailto:curtisr7@gmail.com] 
Sent: Tuesday, December 10, 2013 12:11 AM
To: users
Subject: Re: Incorrect concurrent persist of ManyToOne field

The short story is that in this case you can't share the detached Document across threads
as OpenJPA does use some internal structures to get the id out. I'd suggest changing your
code to utilize the EntityManager.getReference method.

person.setDocument(emCreation.getReference(Document.class,
document.getId()));

Thanks,
Rick


On Mon, Dec 9, 2013 at 1:39 PM, LYALIKOV, Oleg (Oleg) < oleg.lyalikov@alcatel-lucent.com>
wrote:

> Thanks Rick for quick reply,
>
> The project is in attachment.
>
> Forgot to mention - it uses H2 in-memory DB, so no additional setup needed.
> Also on different computers I saw different count of failed objects - 
> on one it's ~1-10 failed objects of 30000 total, on another (slower 
> with less
> cores) ~10-100 failed of 30000 total.
> So feel free to change total objects count and/or threads count (I 
> create Max(4, availableProcessors()) threads, one computer has 4 cores 
> and another
> 2 cores).
>
> Thanks,
> Oleg
>
> -----Original Message-----
> From: Rick Curtis [mailto:curtisr7@gmail.com]
> Sent: Monday, December 09, 2013 11:23 PM
> To: users
> Subject: Re: Incorrect concurrent persist of ManyToOne field
>
> Oleg -
>
> Can you post the maven project with this test? My first thought is 
> that this *should* work, but I can come up with some hypothetical 
> cases where it might not work.
>
> Thanks,
> Rick
>
>
> On Mon, Dec 9, 2013 at 12:02 PM, olyalikov < 
> oleg.lyalikov@alcatel-lucent.com
> > wrote:
>
> > Hello,
> >
> > In short: I have 2 entities - Person and Document, Person has a 
> > ManyToOne link to the Document. I create Document in a separate 
> > thread/entity manager, close entity manager (and so document becomes
> > detached) and then create concurrently Person objects (in separate 
> > entity managers) setting document field to the same detached 
> > Document object I created previously.
> > As a result some of the Person objects are persisted with null value 
> > in the document field (in my tests 1 such Person object for ~2000 
> > "good" Person objects).
> >
> > Full story:
> > OpenJPA 2.2.2 is used + tomcat connection pool + no cache for simplicity.
> > Here are these entities (without setters and getters):
> >
> > @Entity
> > public class Person {
> >     @Id @GeneratedValue
> >     private String id;
> >
> >     @ManyToOne
> >     private Document document;
> > }
> >
> > @Entity
> > public class Document {
> >     @Id @GeneratedValue
> >     private String id;
> > }
> >
> > The code which creates Document:
> >         final Document document = new Document();
> >         final EntityManager em = emf.createEntityManager();
> >         try {
> >                 final EntityTransaction tx = em.getTransaction();
> >                 tx.begin();
> >                 em.persist(document);
> >                 tx.commit();
> >         } finally {
> >                 em.close();
> >         }
> >
> > Then concurrently I create Person objects:
> >         final EntityManager emCreation = emf.createEntityManager();
> >         try {
> >                 for (int j = 0; j < threadObjectCount; j++) {
> >                         final Person person = new Person();
> >                         person.setDocument(document);
> >
> >                         final EntityTransaction tx = 
> > emCreation.getTransaction();
> >                         tx.begin();
> >                         emCreation.persist(person);
> >                         tx.commit();
> >
> >                         emCreation.refresh(person);
> >                         if (person.getDocument() == null) {
> >                                 System.err.println("Person with null 
> > Document found, id=" + person.getId());
> >                         } else {
> >                                 succeded.incrementAndGet();
> >                         }
> >                 }
> >         } finally {
> >                 emCreation.close();
> >         }
> >
> > For some Person objects invocation of "person.getDocument()" returns
> null.
> >
> > Here is a SQL trace when Person is persisted with null Document:
> > 1687  openjpa-concurrent-creation-test  TRACE  [pool-2-thread-3] 
> > openjpa.jdbc.SQL - <t 4934637, conn 22701741> executing prepstmnt
> > 5327894 INSERT INTO Person (id, DOCUMENT_ID) VALUES (?, ?)
> > [params=(String) 1453,
> > (null) null]
> > And here is normal case:
> > 1687  openjpa-concurrent-creation-test  TRACE  [pool-2-thread-1] 
> > openjpa.jdbc.SQL - <t 4358252, conn 30226657> executing prepstmnt
> > 32228587 INSERT INTO Person (id, DOCUMENT_ID) VALUES (?, ?)
> > [params=(String) 1452,
> > (String) 1]
> > There is no more information from OpenJPA logs.
> >
> > Actually I have a maven project with this test and can send it, the 
> > test consistently fails.
> > As a fix it's enough to "find" Document for each new EntityManager 
> > and use it for Person objects.
> >
> > It seems that the Document is correctly published with regard to my 
> > code and other threads (it is not changed by my code after these 
> > threads start) but it may be changed by OpenJPA during Person 
> > persist and in this case this may lead to the inproper view of 
> > Document object in different threads and explain observed behaviour (perhaps).
> >
> > So I have several questions:
> > 1) Is Document object changed by OpenJPA when I persist Person 
> > object (becomes managed or something)?
> > 2) Anyway is it possible to detect this situation by OpenJPA and 
> > react with exception? Or maybe the Document object is not changed 
> > and there is some other issue?
> >
> > Thanks,
> > Oleg
> >
> >
> >
> > --
> > View this message in context:
> > http://openjpa.208410.n2.nabble.com/Incorrect-concurrent-persist-of-
> > Ma nyToOne-field-tp7585744.html Sent from the OpenJPA Users mailing 
> > list archive at Nabble.com.
> >
>
>
>
> --
> *Rick Curtis*
>



--
*Rick Curtis*

Mime
View raw message