Problem with Transactions, EntityManager and dirty-reads


#1

Hello,

I’m using Hibernate ORM 4.3.1 with JPA, JDK 1.7 and MySQL 5.5.34 in InnoDB Mode.
Now my question. A part of my program loads a record from the db, starts an transaction, modifies and commits. After that, the same record will be loaded and modified again multiple times (but in the same thread)

in some cases (I cannot solid reproduce it), the record has an old state. The code looks like this:

Long documentId = 1234l;

EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("TEST");

EntityManager entityManager = null;
try {
  entityManager = entityManagerFactory.createEntityManager();
  entityManager.setFlushMode(FlushModeType.COMMIT);

  //load record first time
  entityManager.getTransaction().begin();
  Document document = entityManager.find(Document.class, documentId);
  document.setStatus("NEW");
  entityManager.getTransaction().commit();
} catch(Exception ex) {
  entityManager.getTransaction().rollback();
} finally {
  entityManager.close();
}

... later....

entityManager = null;
try {
  entityManager = entityManagerFactory.createEntityManager();
  entityManager.setFlushMode(FlushModeType.COMMIT);

  //load record 2nd time
  entityManager.getTransaction().begin();
  Document document = entityManager.find(Document.class, documentId);
  document.setStatus("LOADED");
  document.getXYZObject().setText("ABC");
  entityManager.getTransaction().commit();
} catch(Exception ex) {
  entityManager.getTransaction().rollback();
} finally {
  entityManager.close();
}

...later...

entityManager = null;
try {
  entityManager = entityManagerFactory.createEntityManager();
  entityManager.setFlushMode(FlushModeType.COMMIT);

  //load record 3rd time
  entityManager.getTransaction().begin();
  Document document = entityManager.find(Document.class, documentId);
  document.setStatus("PROCESSED");
  document.getXYZObject().setText("XYZ");
  entityManager.getTransaction().commit();
} catch(Exception ex) {
  entityManager.getTransaction().rollback();
} finally {
  entityManager.close();
}

In 2nd and 3rd step also a child record will be modified (see getXYZObject()).
Sometimes, at the end all changes to the child are persistent in the database (text ist XYZ) but the Document-Object still has the status NEW.

If I repeat this test multiple times, in some times the data of the Document-Object is as i expected, in some times not.

Some ideas?

Best regards!


#2

Maybe that process happens using multiple threads, so the same item is processed concurrently, in which case, one thread sets it to NEW while the other thread has managed to get to step 3.

Without seeing the whole code, it’s impossible to tell for sure what’s wrong.


#3

Hey, no, everything runs in a single thread :frowning:

But: Should the code above work generally or did I miss something?

Best regards!


#4

Very interessting: If i create a checkpoint before modifying in step 3 (!“LOADED”.equals(document.getStatus())", the Status is LOADED and not NEW. At the end (in the Database), the Status is NEW at all.


#5

You need to log all JDBC statements. Afterward, you will better understand where the problem comes from.


#6

I’ve found out, that I cannot ensure modifications or reads on this record from the UI. This might be the problem.
I will implement PESSIMISTIC_WRITE Lock at the right positions and will check, if the problem occurs again,… Thanks!