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-ManyToOne-field-tp7585744.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.

Reply via email to