title: Create new or update existing entity at one go with JPA
body: <p>A have a JPA entity that has timestamp field and is distinguished by a complex identifier field. What I need is to update timestamp in an entity that has already been stored, otherwise create and store new entity with the current timestamp.</p>
  
  <p>As it turns out the task is not as simple as it seems from the first sight. The problem is that in concurrent environment I get nasty "Unique index or primary key violation" exception. Here's my code:</p>
  
  <pre><code>// Load existing entity, if any.
  Entity e = entityManager.find(Entity.class, id);
  if (e == null) {
    // Could not find entity with the specified id in the database, so create new one.
    e = entityManager.merge(new Entity(id));
  }
  // Set current time...
  e.setTimestamp(new Date());
  // ...and finally save entity.
  entityManager.flush();
  </code></pre>
  
  <p>Please note that in this example entity identifier is not generated on insert, it is known in advance.</p>
  
  <p>When two or more of threads run this block of code in parallel, they may simultaneously get <code>null</code> from <code>entityManager.find(Entity.class, id)</code> method call, so they will attempt to save two or more entities at the same time, with the same identifier resulting in error.</p>
  
  <p>I think that there are few solutions to the problem.</p>
  
  <ol>
  <li>Sure I could synchronize this code block with a global lock to prevent concurrent access to the database, but would it be the most efficient way?</li>
  <li>Some databases support very handy <code>MERGE</code> statement that updates existing or creates new row if none exists. But I doubt that OpenJPA (JPA implementation of my choice) supports it.</li>
  <li>Event if JPA does not support SQL MERGE, I can always fall back to plain old JDBC and do whatever I want with the database. But I don't want to leave comfortable API and mess with hairy JDBC+SQL combination.</li>
  <li>There is a magic trick to fix it using standard JPA API only, but I don't know it yet.</li>
  </ol>
  
  <p>Please help.</p>