title: optimistic lock on A OneToMany Relationship
body: <p>I have a one-to-many Category-Products relation:</p>
  
  <pre><code>public class **Category**{
  
      @Version
      private Integer version;
  
      @OneToMany(mappedBy = "category", cascade = {CascadeType.ALL})
      //@OptimisticLock(excluded = true)
      private List&lt;Product&gt; products
  ....
  
  }
  </code></pre>
  
  <p>and the many-to-one side:</p>
  
  <pre><code>public class **Product**{
  
      @Version
      private Integer version;
  
      @ManyToOne
      @JoinColumn(name = "category_id")
      @ForeignKey(name = "fk_category_product")
      //@OptimisticLock(excluded = true)
      private Category category
  ....
  
  }
  </code></pre>
  
  <p>I want to prevent Lost Modifications, so I defined a version mechanism (concurrency control) as above.</p>
  
  <p>But when I want to save my parent entity(Category), I get the following error:</p>
  
  <blockquote>
    <p><strong>could not execute statement; SQL [n/a]; constraint [JOHN.SYS_C0090239]; nested exception is
    org.hibernate.exception.ConstraintViolationException: could not
    execute statement</strong></p>
  </blockquote>
  
  <p>Here is my Action, service and dao layers:</p>
  
  <h2>Action</h2>
  
  <pre><code>public String save() throws Exception {
  
          try {
  
              categoryManager.saveCategory(category);
  
          }catch (CategoryExistException e){
              List&lt;Object&gt; args = new ArrayList&lt;Object&gt;();
              args.add(category.getCategoryName());//categoryName is UNIQUE
              addActionError(getText("errors.existing.category", args));
              return INPUT;
          }
  
  }
  </code></pre>
  
  <h2>Manager</h2>
  
  <pre><code>@Override
  public Category saveCategory(Category category) throws CategoryExistException{
  
      if (category.getVersion()==null)
      {
          // if new category, lowercase categoryId
          category.setCategoryName(category.getCategoryName().toLowerCase());
      }
  
      try {
          return categoryDao.saveCategory(category);
      } catch (final Exception e) {
          e.printStackTrace();
          log.warn(e.getMessage());
          throw new CategoryExistException("Category '" + category.getCategoryName() + "' already exists!");
      }
  }
  </code></pre>
  
  <h2>Dao</h2>
  
  <pre><code>@Override
  public Category saveCategory(Category category){
  
      if (log.isDebugEnabled()) {
          log.debug("category's id: " + category.getCategoryId());
      }
  
  
      getSession().saveOrUpdate(category);
      //getSession().merge(category);
  
      // necessary to throw a DataIntegrityViolation and catch it in CategoryManger
      getSession().flush();
  
  
      return category;
  }
  </code></pre>