title: JPA LockModeType.PESSIMISTIC_WRITE doesn't work as expected. App without keys, reads snapshot of database at locking
body: <p>I have two apps running identical code, querying the same Oracle database with the help of hibernate.<br>
  There is a table that keeps emails to be sent.<br>
  Both apps run a scheduler that query a column on this table for "QUEUED" string (which marks emails to be sent), create and send emails and at the end, update, "QUEUED" to "SENT" so these emails won't be sent again.<br>
  In theory, I want one app to read some rows, lock them from reading and writing, update them and unlocking for the other app to use.<br>
  For this reason I am using below query:  </p>
  
  <pre><code>String jpql = "SELECT m FROM Email m WHERE m.status = :status";
  return em.createQuery(jpql, Email.class)
          .setParameter("status", "QUEUED")
          .setLockMode(LockModeType.PESSIMISTIC_WRITE)
          .getResultList();  
  </code></pre>
  
  <p>which is used by both apps and according to documents, LockModeType.PESSIMISTIC_WRITE is the equivalent of "SELECT FOR UPDATE".<br>
  Instead, below behavior happens:</p>
  
  <pre><code>13:06:02,160 | MailQueueMonitor_1| Found 0 email(s) to be sent. // No rows returned from app1  
  
  13:06:03,813 | MailQueueMonitor_2| Found 0 email(s) to be sent. // No rows returned from app2  
  
  13:06:12,180 | MailQueueMonitor_1| Found 1 email(s) to be sent. // 1 mail returned from app1  
  
  13:06:12,190 | MailQueueMonitor_1| Mailer will sleep for 30s    // App1 will sleep for 30s   
  
  // At this point, app2 tries to execute query but freezes as app1 has the keys to the rows  
  
  13:06:42,191 | MailQueueMonitor_1| Mailer woke up and will try to send mails    // App1 wakes up  
  
  13:06:46,796 | MailQueueMonitor_1| Mailer sent mail     // App1 sent mail  
  
  13:06:46,798 | MailQueueMonitor_1| Mailer changed mail status to SENT // App1 update status from QUEUED to SENT  
  
  // At this point, app1 releases the locks and app2 unfreezes and executes query looking for QUEUED rows which should not exist at this point since they where updated to SENT.  
  
  13:06:46,809 | MailQueueMonitor_2| Found 1 email(s) to be sent. // App2 queries and finds 1 row! It is like it queried a snapshot of the database before app2 updated all rows.  
  
  13:06:46,836 | MailQueueMonitor_2| Mailer will sleep for 30s    // App2 will sleep for 30s  
  
  13:07:16,836 | MailQueueMonitor_2| Mailer woke up and will try to send mails    // App2 wakes up  
  
  13:07:21,457 | MailQueueMonitor_2| Mailer sent mails    // App2 sent mail. This is re-senting above email occuring to duplicate emails.  
  
  13:07:21,458 | MailQueueMonitor_2| Mailer changed mail status SENT  // App2 update status from QUEUED to SENT, again!
  </code></pre>
  
  <p>The questions are, why doesn't app2 read updated rows even though, query is executed after lock release.
  Why isn't an exception thrown when app2 tries to query locked rows?
  How should I lock the rows from being read or updated and after lock released, the next app which will query the db will see the updated data?  </p>
  
  <p>Some notes:<br>
  1. If I run the query twice on two consecutive lines, when the locks are released, the previously locked app will execute first query (which was the one locked) will return non-updated data but the second will return updated data by app which previously had the locks.<br>
  2. If I manually run above procedure through two ORACLE SQL DEVELOPER instances, the behavior is as expected, meaning:  </p>
  
  <pre><code>SQL_DEV_1: SELECT * FROM T_MAIL WHERE STATUS = 'QUEUED' FOR UPDATE; // Returns 1 row, locks the row
  SQL_DEV_2: SELECT * FROM T_MAIL WHERE STATUS = 'QUEUED' FOR UPDATE; // Doesn't return anything but keeps waiting for locks to be released
  SQL_DEV_1: UPDATE T_MAIL SET STATUS = 'SENT'; // Returns 1 row, locks the row
  SQL_DEV_1: COMMIT; // Commit update, locks are released
  SQL_DEV_2: // waiting query is executed, returns no rows since one and only row was update to SENT
  </code></pre>