title: SELECT query with composite primary key
body: <p>In a spring mvc app using hibernate and jpa, I recently switched to a composite primary key using an <code>@Embeddable</code> class.  As a result, I need to update the JPA query that returns a given object based on its unique id.  The following is the JPA code that used to work, but which no longer returns a result:  </p>
  
  <pre><code>@SuppressWarnings("unchecked")
  public Concept findConceptById(BigInteger id) {
      Query query = this.em.createQuery("SELECT conc FROM Concept conc WHERE conc.id =:cid");
      query.setParameter("cid", id);
      return (Concept) query.getSingleResult();
  }
  </code></pre>
  
  <p><strong>How do I change the above query so that it returns the Concept with the most recent <code>effectiveTime</code> for the given <code>id</code>?</strong>  Note that <code>id</code> and <code>effectiveTime</code> are the two properties of the <code>ConceptPK</code>  composite primary key, and that thus the property definitions and getters and setters for <code>id</code> and <code>effectiveTime</code> are in the <code>ConceptPK</code> class and NOT in the <code>Concept</code> class.  </p>
  
  <p>The error thrown by the above is:  </p>
  
  <pre><code>Caused by: java.lang.IllegalArgumentException:  
  Parameter value [786787679] did not match expected type [myapp.ConceptPK]  
  </code></pre>
  
  <p>This is how the primary key is now defined in the <code>Concept</code> class:  </p>
  
  <pre><code>private ConceptPK conceptPK;  
  </code></pre>
  
  <p>And here is the code for the <code>ConceptPK</code> class:  </p>
  
  <pre><code>@Embeddable
  class ConceptPK implements Serializable {
  
      @Column(name="id", nullable=false)
      protected BigInteger id;
  
      @Column(name="effectiveTime", nullable=false)
      @Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
      private DateTime effectiveTime;
  
      public ConceptPK() {}
      public ConceptPK(BigInteger bint, DateTime dt) {
          this.id = bint;
          this.effectiveTime = dt;
      }
  
      /** getters and setters **/
      public DateTime getEffectiveTime(){return effectiveTime;}
      public void setEffectiveTime(DateTime ad){effectiveTime=ad;}
  
      public void setId(BigInteger id) {this.id = id;}
      public BigInteger getId() {return id;}
  
      @Override
      public boolean equals(Object obj) { 
          if (this == obj) return true;
          if (obj == null) return false;
          if (getClass() != obj.getClass()) return false;
          final ConceptPK other = (ConceptPK) obj;
          if (effectiveTime == null) {
              if (other.effectiveTime != null) return false;
              } else if (!effectiveTime.equals(other.effectiveTime)) return false;
          if (id == null) {
              if (other.id != null) return false;
          } else if (!id.equals(other.id)) return false;
          return true;
      }
  
      @Override
      public int hashCode() { 
          int hash = 3;
          hash = 53 * hash + ((effectiveTime == null) ? 0 : effectiveTime.hashCode());
          hash = 53 * hash + ((id == null) ? 0 : id.hashCode());
          return hash;
      }
  }
  </code></pre>