title: JPA: merging entities based on a 'natural key'
body: <p>Possibly I'm understanding the concept wrong, but here is my problem:</p>
  
  <p>I want to store two types of data in my database:</p>
  
  <ol>
  <li>game positions (uniquely represented by some lengthy string, containing two lists of moves - one for moves possible in this position and one for moves leading to this position)</li>
  <li>game moves (represented by a smaller string, linking two positions)</li>
  </ol>
  
  <p>In classes:</p>
  
  <pre><code>@Entity
  public class Move {
      @Id
      @GeneratedValue
      private long id;
      private String representation;
      private Position positionBeforeMove;
      private Position positionAfterMove;
  
      ...
  }
  
  @Entity 
  public class Position {
      @Id
      private String representation;
      private List&lt;Move&gt; movesLeadingToPosition;
      private List&lt;Move&gt; movesLeadingFromPosition;
  
      ...
  }
  </code></pre>
  
  <p>I want to store a set of games. In this context, the positions are unique, and the moves may occur multiple times in the database.</p>
  
  <p>My naieve implementation uses two tables:</p>
  
  <pre><code>MOVE
  number   id                    (PK)
  varchar2 representation
  varchar2 positionBeforeMove    (FK)
  varchar2 positionAfterMove     (FK)
  ...
  
  POSITION
  varchar2 representation        (PK)
  ...
  </code></pre>
  
  <p>This works fine; using <code>EntityManager.merge(position)</code> I can grow my <code>POSITION</code> table as I store more and more games, while keeping the positions unique.</p>
  
  <p>However, the solution is not optimal: I'd much prefer to have a generated <code>id</code> like I have in the MOVE table! </p>
  
  <pre><code>@Entity
  public class Position {
      @Id
      @GeneratedValue
      private long id;
  
      private String representation;
      private List&lt;Move&gt; movesLeadingToPosition;
      private List&lt;Move&gt; movesLeadingFromPosition;
  
      ...
  }
  
  MOVE
  number   id                    (PK)
  varchar2 representation
  number   positionBeforeMove_id (FK)
  number   positionAfterMove_id  (FK)
  ...
  
  POSITION
  number id;                     (PK)
  varchar2 representation        (Unique)
  ...
  </code></pre>
  
  <p>But when I implement this, I end up with duplicate representations, because the <code>EntityManager.merge(...)</code> merges based on the <em>specified</em> Id, not the <em>natural</em> key.</p>
  
  <p>Is there any way I can let java (JPA / Hibernate / ...) merge the positions based on the natural key, while still allowing me to use an ID as the key to the table? Or, would I need to merge the positions manually? (for example: Whenever I want to store a move, would I need to retrieve the <code>positionAfterMove</code> and <code>positionBeforeMove</code> from the database, add the move to <code>movesLeadingToPosition</code> and <code>movesLeadingFromPosition</code> respectively, and then update the positions in the database?)</p>
  
  <p>(context: I'm using Java 1.7, JPA, and a MySQL database)</p>