title: Hibernate: Insert objects with unique constraints from different threads
body: <p>I have the following problem. I have 10 Threads which create objects that are inserted in the database. Each Thread has a ThreadLocal and its own session. All objects are inserted together, after they were created. These objects have a column which is marked as unique. However, I have the problem, that it can happen that two different threads create the same object. This behaviour is wanted but I don't know how I can insert them into my database. </p>
  
  <p>Currently, each thread queries all objects that are inserted in the database, checks on the queried objects if they exist or not and inserts the non-existing objects into the database. However, as it can happen that the object did not exist on the query of all objects, I get a <em>ConstraintViolationException</em> when I insert the objects and they were already added by another Thread. However, doing a database (or cache) query for each object has to bad performance, as we are trying to add 1000 objects per thread and minute. If I try to flush the database after each single insert, then I get the following error: <em>Deadlock found when trying to get lock; try restarting transaction</em> </p>
  
  <p>So my question is: How can I insert objects, that have a unique constraint from different threads simultanously.</p>
  
  <p>//Edit: currently I'm using Hibernate with MYSQL InnoDB</p>
  
  <p>//Edit2: Finally, the code which I use to write a single item.</p>
  
  <pre><code>public class ItemWriterRunnable implements Callable&lt;Object&gt; {
  
      private final ThreadLocal&lt;Session&gt; session = new ThreadLocal&lt;Session&gt;();
  
      private Item item;
  
      public ItemWriterRunnable(Item item) {
          super();
          this.item= item;
      }
  
      protected Session currentSession() {
          Session s = this.session.get();
          // Open a new Session, if this thread has none yet
          if (s == null || !s.isOpen()) {
              s = HibernateUtils.getSessionFactory().openSession();
              // Store it in the ThreadLocal variable
              this.session.set(s);
          }
          return s;
      }
  
      @Override
      public Object call() throws Exception {
          Session currentSession = currentSession();
          try {
              currentSession.beginTransaction();
              currentSession.save(this.item);
              currentSession.getTransaction().commit();
          } catch (ConstraintViolationException e) {
              currentSession.getTransaction().rollback();
          } catch (RuntimeException e) {
              currentSession.getTransaction().rollback();
          } finally {
              currentSession.close();
              currentSession = null;
              this.session.remove();
          }
          return null;
      }
  }
  </code></pre>
  
  <p>Best regards,
  André </p>