title: Spring data - Concurrent create-if-not-exists leads to duplicate entires
body: <p>I have the following code, that is run in multiple threads:</p>
  
  <pre><code>@Component
  public class CreateInstrumentTask {
  
     @Autowired
     InstrumentRepository repository; // Spring-data JPA repo interface
  
     @Transactional
     public void createInstrument(String instrumentId) {
        synchronized(instrumentId.intern()) {
           QInstrument $instrument = QInstrument.instrument;
           Instrument instrument = repository.findOne($instrument.instrumentId.eq(instrumentId));
  
           if (instrument == null) {
              log.info("Thread {} creating instrument {}", Thread.currentThread().getName(), message.getInstrumentId());
  
              instrument = createInstrument(instrumentId); // impl. ommitted
              repository.saveAndFlush(instrument);
           }
        }
     }
  </code></pre>
  
  <p>This logs out:</p>
  
  <pre><code>INFO [] Thread taskExecutor-1 creating instrument ABC
  INFO [] Thread taskExecutor-17 creating instrument ABC
  org.springframework.integration.MessageHandlingException:       
  org.springframework.dao.DataIntegrityViolationException: Duplicate entry 'ABC' for key 'instrumentId';
  </code></pre>
  
  <p>I expected that, given the code is <code>synchronized</code> against the <code>instrumentId</code>, that duplicates should be prevented.</p>
  
  <p>However, I guess that because the code is transactional, and the boundaries of the transaction are at the method, (not the synchronized block), that the lock is released before the transaction has persisted, allowing the duplicates.</p>
  
  <p>This must be a fairly common pattern ("create-if-not-exists").  What is the correct recipe for performing this in a concurrent fashion?</p>