views:

50

answers:

1

This is my code, which I can't even compile:

/**
 * Find a project that has NO employee assigned yet.
 */
public Project findEmptyProject() {
  // getting criteria builder
  CriteriaBuilder cb = this.em.getCriteriaBuilder();
  // gathering meta information about left-joined entity
  Metamodel m = this.em.getMetamodel();
  EntityType<Employee> Employee_ = m.entity(Employee.class);
  // creating query
  CriteriaQuery<Project> cq = cb.createQuery(Project.class);
  // setting query root for the query
  Root<Project> project = cq.from(Project.class);
  // left-joining with another employees
  Join<Employee, Project> projects = project.join(
    Employee_.project, 
    JoinType.LEFT
  );
  // instructing the query to select only projects
  // where we have NO employees
  cq.select(project).where(Employee_.id.isNull());
  // fetching real data from the database
  return this.em.createQuery(cq).getSingleResult();
}

My model classes are:

public class Employee {
  @Id private Integer id;
  @ManyToOne private Project project;
  private String name;
}

public class Project {
  @Id private Integer id;
  private String name;
}

Compiler says (and I would say the same being a compiler):

Finder.java: cannot find symbol: variable project
location: interface javax.persistence.metamodel.EntityType<com.XXX.Employee>

What am I doing wrong?

+1  A: 

When you use Employee_.project syntax, Employee_ must be an autogenerated metamodel class, not an EntityType obtained via Metamodel.entity().

Hibernate JPA 2 Metamodel Generator manual explains how to configure generation of these classes in Hibernate.

axtavt
@axtavt But this is what I've taken from tutorial (http://download.oracle.com/javaee/6/tutorial/doc/gjivm.html). The tutorial is wrong?
Vincenzo
@Vincenzo: It's astonishing, but the tutorial is wrong. Authors of tutorial confused dynamic metamodel (obtained via `getMetamodel()`) with static metamodel (generated by processing tools). Only static metamodel can be used to access properties such as `Employee_.project`. By the way, you query is also wrong - this kind of query would require `RIGHT JOIN` in JPQL, but Criteria API doesn't support right joins. You can rewrite it with subquery and `NOT EXISTS`.
axtavt