JPA 2.0,Criteria API,子查询,expression式

我试图用子查询和一个INexpression式多次写查询语句。 但我从来没有成功。

我总是得到exception,“附近关键字”IN“的语法错误”,查询语句是这样构build的,

 SELECT t0.ID, t0.NAME FROM EMPLOYEE t0 WHERE IN (SELECT ? FROM PROJECT t2, EMPLOYEE t1 WHERE ((t2.NAME = ?) AND (t1.ID = t2.project))) 

“IN”输之前我知道这个词。

你有没有写过这样的查询? 任何build议?

以下是使用Criteria API使用子查询的伪代码。

 CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); CriteriaQuery<Object> criteriaQuery = criteriaBuilder.createQuery(); Root<EMPLOYEE> from = criteriaQuery.from(EMPLOYEE.class); Path<Object> path = from.get("compare_field"); // field to map with sub-query from.fetch("name"); from.fetch("id"); CriteriaQuery<Object> select = criteriaQuery.select(from); Subquery<PROJECT> subquery = criteriaQuery.subquery(PROJECT.class); Root fromProject = subquery.from(PROJECT.class); subquery.select(fromProject.get("requiredColumnName")); // field to map with main-query subquery.where(criteriaBuilder.and(criteriaBuilder.equal("name",name_value),criteriaBuilder.equal("id",id_value))); select.where(criteriaBuilder.in(path).value(subquery)); TypedQuery<Object> typedQuery = entityManager.createQuery(select); List<Object> resultList = typedQuery.getResultList(); 

此外,它肯定需要一些修改,因为我试图根据您的查询映射。 这是一个链接http://www.ibm.com/developerworks/java/library/j-typesafejpa/ ,它很好地解释了概念。

晚期复活。

您的查询看起来与Pro JPA 2专书第259页中的非常相似:掌握 JPQL中的Java持久性API :

 SELECT e FROM Employee e WHERE e IN (SELECT emp FROM Project p JOIN p.employees emp WHERE p.name = :project) 

使用EclipseLink + H2数据库,我既没有得到本书的JPQL也没有得到相应的标准。 对于这个特殊的问题,我发现如果你直接引用这个id,而不是让持久化提供者把它看成一切正常,

 SELECT e FROM Employee e WHERE e.id IN (SELECT emp.id FROM Project p JOIN p.employees emp WHERE p.name = :project) 

最后,为了解决您的问题,下面是一个等效的强types标准查询:

 CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Employee> c = cb.createQuery(Employee.class); Root<Employee> emp = c.from(Employee.class); Subquery<Integer> sq = c.subquery(Integer.class); Root<Project> project = sq.from(Project.class); Join<Project, Employee> sqEmp = project.join(Project_.employees); sq.select(sqEmp.get(Employee_.id)).where( cb.equal(project.get(Project_.name), cb.parameter(String.class, "project"))); c.select(emp).where( cb.in(emp.get(Employee_.id)).value(sq)); TypedQuery<Employee> q = em.createQuery(c); q.setParameter("project", projectName); // projectName is a String List<Employee> employees = q.getResultList();