title: Hibernate: Replacing object (OneToOne)
body: <p>I have a parent entity <code>Stock</code> which has a child entity <code>StockDetails</code> in a OneToOne relation.
  I can't figure out how to properly set and replace values for the <code>Stock.details</code> field.</p>
  <p>Here are my entity classes (@Getter/@Setter from Lombok):</p>
  <pre><code>@Getter
  @Setter
  @NoArgsConstructor
  @Entity
  @Table(name = &quot;stocks&quot;)
  public class Stock
  {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
  
    private String isin;
    private String symbol;
    private String name;
  
    @OneToMany(mappedBy = &quot;stock&quot;, cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
    private List&lt;StockChartPoint&gt; chart;
  
    @OneToOne(mappedBy = &quot;stock&quot;, cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
    private StockDetails details;
  
    public void setDetails(StockDetails d)
    {
      details = d;
      details.setStock(this);
    }
  
  }
  </code></pre>
  <p>and</p>
  <pre><code>@Getter
  @Setter
  @NoArgsConstructor
  @Entity
  @Table(name = &quot;stock_details&quot;)
  public class StockDetails
  {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
  
    @OneToOne
    @JoinColumn(name = &quot;stock&quot;)
    private Stock stock;
  }
  </code></pre>
  <p>Inserting a new value (and corresponding row) into the DB works fine when the details table is empty and I can see that Hibernate logs exactly one intert statement. My code looks like this:</p>
  <pre><code>dbService.transactional(session -&gt;
  {
    var stocks = getAllStocks();
    var s = stocks.get(0);
  
    StockDetails n = new StockDetails();
    s.setDetails(n);
    session.save(s);
  });
  </code></pre>
  <p>The <code>DbService.transactional</code> method (<code>TransactionExecutor</code> is just a functional interface):</p>
  <pre><code>public void transactional(TransactionExecutor executor)
  {
    Transaction t = null;
    try
    {
      t = session.beginTransaction();
      executor.execute(session);
      session.flush();
      t.commit();
    }
    catch (HibernateException ex)
    {
      if (t != null)
        t.rollback();
    }
  }
  </code></pre>
  <p>But when there is already an existing row in the details table the old row is deleted and a new row is inserted. The result is that the PK of the details table is increasing every time I update the values. Is there a pattern which I couldn't find to address this? I could also just update the existing <code>Stock.details</code> field but this would lead in just copying all the fields from object A to object B and I guess there is a smarter way doing this. I tried using an <code>EntityManager</code>, <code>merge()/saveOrUpdate()/persist()</code> instead of <code>save()</code> as well as manipulating the ID in the new object but this resulted in changing nothing or throwing exceptions.</p>
  <p>Then there is another problem I encountered and I don't know if it's related to the first one:
  When executing the <code>dbService.transactional(...)</code> block twice it behaves differently: Now two rows are added to the DB. The SQL log looks like this:</p>
  <pre><code>...
  Hibernate: insert into stock_details (stock) values (?)
  Hibernate: delete from stock_details where id=?
  -&gt; insert/delete produces by the first run
  Hibernate: select stock0_.id as id1_3_, stock0_.isin as isin2_3_, stock0_.name as name3_3_, 
  stock0_.symbol as symbol4_3_ from stocks stock0_
  Hibernate: insert into stock_details (stock) values (?)
  -&gt; Just insert, no delete
  </code></pre>
  <p>Please let me know if more information is needed.</p>
  <ul>
  <li>mysql.mysql-connector-java &gt; 8.0.22</li>
  <li>org.hibernate.hibernate-core &gt; 5.4.25.Final</li>
  <li>org.hibernate.hibernate-validator &gt; 5.4.3.Final</li>
  </ul>