title: Simple where condition for JPA CriteriaQuery
body: <p>So this is my first attempt to use JPA and a <code>CriteriaQuery</code>. </p>
  
  <p>I have the following (simplified) entities:</p>
  
  <pre><code>@Entity
  @Table(name = "hours")
  @XmlRootElement
  public class Hours implements Serializable
  {
      @EmbeddedId
      protected HoursPK hoursPK;
  
      @Column(name = "total_hours")
      private Integer totalHours;
  
      @JoinColumn(name = "trainer_id", referencedColumnName = "id", nullable = false, insertable = false, updatable = false)
      @ManyToOne(optional = false, fetch = FetchType.LAZY)
      private Trainer trainer;
  
      public Hours()
      {
      }
  
      ... getter and setter for the attributes
  }
  
  @Embeddable
  public class HoursPK implements Serializable
  {
      @Basic(optional = false)
      @Column(name = "date_held", nullable = false)
      @Temporal(TemporalType.DATE)
      private Date dateHeld;
  
      @Basic(optional = false)
      @Column(name = "trainer_id", nullable = false, length = 20)
      private String trainerId;
  
      @Column(name = "total_hours")
      private Integer totalHours;
  
  
      public HoursPK()
      {
      }
  
      ... getter and setter ...
  }
  
  @Entity
  @Table(name = "trainer")
  public class Trainer implements Serializable
  {
      @Id
      @Basic(optional = false)
      @Column(name = "id", nullable = false, length = 20)
      private String id;
  
      @Basic(optional = false)
      @Column(name = "firstname", nullable = false, length = 200)
      private String firstname;
  
      @Basic(optional = false)
      @Column(name = "lastname", nullable = false, length = 200)
      private String lastname;
  
      @OneToMany(cascade = CascadeType.ALL, mappedBy = "trainer", fetch = FetchType.LAZY)
      private List&lt;Hours&gt; hoursList;
  
      ... more attributes, getters and setters
  
      @XmlTransient
      public List&lt;Hours&gt; getHoursList() {
         return hoursList;
      }
  
      public void setHoursList(List&lt;Hours&gt; hoursList) {
        this.hoursList = hoursList;
      }
  }
  </code></pre>
  
  <p>Essentially a <code>Trainer</code> holds trainings and the hours spent in the trainings are stored in the <code>Hours</code> entity. The PK for the <code>hours</code> table is (<code>trainer_id, date_held)</code> as each trainer only holds one training per day.</p>
  
  <p>I am trying to create a <code>CriteriaQuery</code> to fetch all hours of a trainer for a specific month. This is my attempt:</p>
  
  <pre><code>EntityManagerFactory emf = ...
  EntityManager em = emf.createEntityManager();
  CriteriaBuilder builder = em.getCriteriaBuilder();
  
  CriteriaQuery&lt;Hours&gt; c = builder.createQuery(Hours.class);
  
  Root&lt;Hours&gt; root = c.from(Hours.class);
  
  Calendar cal = Calendar.getInstance();
  cal.set(2014, 0, 1);
  Expression&lt;Date&gt; from = builder.literal(cal.getTime());
  
  cal.set(2014, 1, 1);
  Expression&lt;Date&gt; to = builder.literal(cal.getTime());
  
  Predicate who = builder.equal(root.get(Hours_.trainer), "foobar"); // it fails here
  
  Predicate gt = builder.greaterThanOrEqualTo(root.get(Hours_.hoursPK).get(HoursPK_.dateHeld), from);
  Predicate lt = builder.lessThan(root.get(Hours_.hoursPK).get(HoursPK_.dateHeld), to);
  
  c.where(gt,lt,who);
  c.orderBy(builder.asc( root.get(Hours_.hoursPK).get(HoursPK_.dateHeld)  ));
  
  TypedQuery&lt;Hours&gt; q = em.createQuery(c);
  
  List&lt;Hours&gt; resultList = q.getResultList();
  </code></pre>
  
  <p>I'm using Hibernate 4.3.1 as the JPA provider and the above code fails with the exception:</p>
  
  <blockquote>
    <p>Exception in thread "main" java.lang.IllegalArgumentException: Parameter value [foobar] did not match expected type [persistence.Trainer (n/a)]
        at org.hibernate.jpa.spi.BaseQueryImpl.validateBinding(BaseQueryImpl.java:885)</p>
  </blockquote>
  
  <p>Apart from the fact that this seems awfully complicated for a query that even a SQL newbie could write in a few minutes, I have no clue, how I can supply the correct value for the <code>trainer_id</code> column in the <code>hours</code> table in the above query. </p>
  
  <p>I also tried:</p>
  
  <pre><code>Predicate who = builder.equal(root.get("trainer_id"), "foobar");
  </code></pre>
  
  <p>But that fails with the exception: </p>
  
  <blockquote>
    <p>java.lang.IllegalArgumentException: Unable to locate Attribute  with the the given name [trainer_id] on this ManagedType [persistence.Hours]</p>
  </blockquote>
  
  <p>It works, when I obtain an actual entity instance that maps to the <code>"foobar"</code> id:</p>
  
  <pre><code>CriteriaQuery&lt;Trainer&gt; cq = builder.createQuery(Trainer.class);
  Root&lt;Trainer&gt; trainerRoot = cq.from(Trainer.class);
  cq.where(builder.equal(trainerRoot.get(Trainer_.id), "foobar"));
  TypedQuery&lt;Trainer&gt; trainerQuery = em.createQuery(cq);  
  Trainer foobarTrainer = trainerQuery.getSingleResult();
  ....
  Predicate who = builder.equal(root.get(Hours_.trainer), foobarTrainer);
  </code></pre>
  
  <p>But that seems a pretty stupid (and slow) way to do it.</p>
  
  <p>I'm sure I'm missing something really obvious here, but I can't find it.</p>