title: java - Hibernate merge is generating new rows instead of updating
body: <p>I am using <code>Hibernate-EntityManager version  4.3.5</code>. I have multiple tables using an id with a generated value.</p>
  
  <p>Inserting and such works fine, but when I try to merge Hibernate does not update the old rows and creates new ones. </p>
  
  <p>The content is the same, but the id is incrementing.</p>
  
  <p>Before merge:
  <img src="https://i.stack.imgur.com/hLTBb.png" alt="Before merge"></p>
  
  <p>After merge: 
  <img src="https://i.stack.imgur.com/mSY1N.png" alt="After merge"></p>
  
  <p>I tried to use a custom Id generator to check if the Id already exists. With this new strategy i get the following error:</p>
  
  <pre><code>Caused by: java.sql.SQLException: Field 'product_id' doesn't have a default value
  at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1094)
  at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4226)
  at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4158)
  at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2615)
  </code></pre>
  
  <p><strong>EDIT</strong>:</p>
  
  <p>I found out that @GeneratedValues will not set the ids in the local variables. That means that you might override the existing ones while merging. Though, that did not solve my problem.</p>
  
  <p>Here is the code I am using:</p>
  
  <pre><code>@Entity(name = "calculation_storage")
  @Proxy(lazy = false)
  public class CalculationStorage {
  
  @Id
  private Date created;
  
  @OneToMany(mappedBy = "storage", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
  private List&lt;Product&gt; products;
  
  public CalculationStorage(Date created) {
      this.created = created;
      this.products = new LinkedList&lt;Product&gt;() {
          @Override
          public boolean add(Product product) {
              product.setStorage(CalculationStorage.this);
              return super.add(product);
          }
      };
  }
  
  public CalculationStorage(Date created, List&lt;Product&gt; products) {
      this.created = created;
      this.products = products;
  }
  
  public CalculationStorage() {
  }
  
  public Date getCreated() {
      return created;
  }
  
  public void setCreated(Date created) {
      this.created = created;
  }
  
  /**
   * Durch das aufrufen get add Methode wird der benoetigte Fremdschluesseleintrag gesetzt
   *
   * @return Alle Produkte die registriert sind
   */
  public List&lt;Product&gt; getProducts() {
      return products;
  }
  
  public void setProducts(List&lt;Product&gt; entities) {
      this.products = entities;
  }
  </code></pre>
  
  <p>Produkt:</p>
  
  <pre><code>@Entity(name = "product")
  public class Product implements Serializable {
  
  @Id
  @Column(name = "product_id")
  //@GeneratedValue
  @GeneratedValue(strategy=GenerationType.IDENTITY, generator="IdOrGenerated")
  @GenericGenerator(name="IdOrGenerated",
          strategy="at.iktopia.firmenverwaltung.abendabrechnung.control.hibernate.ProductIdGenerator"
  )
  private int id;
  
  private double costs;
  
  private String name;
  
  private ProductType type;
  
  @OneToMany(mappedBy = "product", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
  private List&lt;CalculatorEntity&gt; entities;
  
  @ManyToOne
  @JoinColumn(name = "product_fk", nullable = false)
  private CalculationStorage storage;
  
  public Product(String name, ProductType type, double costs) {
      this.name = name;
      this.type = type;
      this.costs = costs;
      this.entities = new LinkedList&lt;&gt;();
  }
  
  /**
   * JPA - Konstruktor
   */
  public Product() {
  }
  
  public int getId() {
      return id;
  }
  
  public void setId(int id) {
      this.id = id;
  }
  
  public String getName() {
      return name;
  }
  
  public void setName(String name) {
      this.name = name;
  }
  
  public ProductType getType() {
      return type;
  }
  
  public void setType(ProductType type) {
      this.type = type;
  }
  
  public List&lt;CalculatorEntity&gt; getEntities() {
      return entities;
  }
  
  public void setEntities(List&lt;CalculatorEntity&gt; entities) {
      this.entities = entities;
  }
  
  public double getCosts() {
      return costs;
  }
  
  public void setCosts(double costs) {
      this.costs = costs;
  }
  
  public CalculationStorage getStorage() {
      return storage;
  }
  
  public void setStorage(CalculationStorage calculationStorage) {
      this.storage = calculationStorage;
  }
  }
  </code></pre>
  
  <p>The Generator:</p>
  
  <pre><code>public class ProductIdGenerator extends IdentityGenerator {
  @Override
  public Serializable generate(SessionImplementor session, Object obj) throws HibernateException {
      if (obj == null) throw new HibernateException(new NullPointerException());
  
      if ((((Product) obj).getId()) == 0) return super.generate(session, obj);
  
      else return ((Product) obj).getId();
  }
  }
  </code></pre>
  
  <p>The update method that is called to merge the object:</p>
  
  <pre><code>public class CalculationManager implements Manager&lt;CalculationStorage, Date, CalculationStorageList&gt; {
  
  /**
   * @see Manager#save(Object)
   */
  @Override
  public void save(CalculationStorage calculationStorage) {
      Validate.notNull(calculationStorage);
  
      EntityManager em = PersistenceManager.getInstance().getEntityManager();
      EntityTransaction transaction = em.getTransaction();
  
      transaction.begin();
  
      try {
          em.persist(calculationStorage);
          transaction.commit();
      } catch (Exception e) {
          ErrorHandler.handleException(e, JPA_PERSIST_ERROR_MESSAGE);
          if (transaction.isActive())
              transaction.rollback();
      }
  
      em.close();
  }
  
  /**
   * @see Manager#update(Object)
   */
  @Override
  public void update(CalculationStorage calculations) {
      Validate.notNull(calculations);
  
      EntityManager em = PersistenceManager.getInstance().getEntityManager();
      EntityTransaction transaction = em.getTransaction();
  
      transaction.begin();
  
      try {
          CalculationStorage c = em.getReference(CalculationStorage.class, calculations.getCreated());
          c.setProducts(calculations.getProducts());
  
          em.merge(c);
  
          transaction.commit();
      } catch (EntityNotFoundException e) {
          if (transaction.isActive())
              transaction.rollback();
          save(calculations);
      } catch (Exception e) {
          ErrorHandler.handleException(e, JPA_PERSIST_ERROR_MESSAGE);
          if (transaction.isActive())
              transaction.rollback();
      }
  
      em.close();
  }
  
  /**
   * @see Manager#getAll()
   */
  @Override
  public CalculationStorageList getAll() {
      EntityManager em = PersistenceManager.getInstance().getEntityManager();
  
      List&lt;CalculationStorage&gt; calculations;
  
      try {
          calculations = em.createQuery("SELECT c FROM calculation_storage c").getResultList();
      } catch (Exception e) {
          ErrorHandler.handleException(e, JPA_LOAD_ERROR_MESSAGE);
          return null;
      }
  
      em.close();
  
      return new CalculationStorageList(calculations);
  }
  
  /**
   * @see Manager#remove(Object)
   */
  @Override
  public void remove(Date primaryKey) {
      Validate.notNull(primaryKey);
  
      EntityManager em = PersistenceManager.getInstance().getEntityManager();
      EntityTransaction transaction = em.getTransaction();
  
      transaction.begin();
  
      try {
          em.remove(em.getReference(CalculationStorage.class, primaryKey));
          transaction.commit();
      } catch (Exception e) {
          ErrorHandler.handleException(e, JPA_PERSIST_ERROR_MESSAGE);
          if (transaction.isActive())
              transaction.rollback();
      }
  
      em.close();
  }
  
  /**
   * @see Manager#get(Object)
   */
  @Override
  public CalculationStorage get(Date primaryKey) {
      Validate.notNull(primaryKey);
  
      EntityManager em = PersistenceManager.getInstance().getEntityManager();
  
      try {
          CalculationStorage storage = em.getReference(CalculationStorage.class, primaryKey);
          em.close();
          return storage;
      } catch (Exception e) {
          ErrorHandler.handleException(e, JPA_LOAD_ERROR_MESSAGE);
          return null;
      }
  }
  }
  </code></pre>
  
  <p>I am clueless what could cause this issue.</p>