【发布时间】:2017-12-11 20:32:13
【问题描述】:
给定这个 SQL 查询
SELECT
ug.lookup_key,
count(ug.id) as count
FROM user u
INNER JOIN user_group ug on ug.id = u.id
WHERE
u.age >= 11 AND
u.age <= 20 AND
ug.lookup_key in('12345')
GROUP BY ug.lookup_key
HAVING count(ug.id) < 7
我已经写好了
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Object[]> query = criteriaBuilder.createQuery(Object[].class);
Root<UserGroup> d = query.from(UserGroup.class);
Join<UserGroup, User> join = d.join("users");
Predicate pred1 = criteriaBuilder.between(join.get("age"), ageFrom, ageTo);
Expression<String> exp = d.get("lookupKey");
Predicate pred2 = exp.in(lookupKeys);
query.where(pred1, pred2);
query.multiselect(d.get("lookupKey"), criteriaBuilder.count(d.get("id"))).groupBy(d.get("lookupKey"));
List<Object[]> results = entityManager.createQuery(query).getResultList();
for(Object[] object : results){
System.out.println(object[0] + " " + object[1]);
}
SQL 返回 {"12345",4} 而代码返回 {"12345", 37}。 SQL 是正确的结果。数据库中有 37 个用户用于具有该查找键的组,因此我了解数字的来源,但我不明白如何使用 CreateCriteria 查询执行 JOIN、GROUP BY、HAVING 以获得结果。我不想使用 JPQL。
实体...
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
private int age;
private double salary;
@ManyToOne(optional=false,cascade=CascadeType.ALL, targetEntity=UserGroup.class)
@JsonBackReference
private UserGroup group;
// Getters and Setters //
}
@Entity
public class UserGroup {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
private String lookupKey;
@OneToMany(mappedBy="group",targetEntity=User.class, fetch=FetchType.EAGER)
@JsonManagedReference
private Collection users;
// Getters and Setters //
}
还有,这是实现它的方法
public void summarizeGroupsByLookupKey(long ageFrom, long ageTo, List<String> lookupKeys, long numUsers){
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Object[]> query = criteriaBuilder.createQuery(Object[].class);
Root<UserGroup> d = query.from(UserGroup.class);
Join<UserGroup, User> join = d.join("users");
Predicate pred1 = criteriaBuilder.between(join.get("age"), ageFrom, ageTo);
Expression<String> exp = d.get("lookupKey");
Predicate pred2 = exp.in(lookupKeys);
query.where(pred1, pred2);
query.multiselect(d.get("lookupKey"), criteriaBuilder.count(d.get("id")));
query.groupBy(d.get("lookupKey"));
query.having(criteriaBuilder.<Long>lessThan(criteriaBuilder.count(d.get("id")), numUsers));
List<Object[]> results = entityManager.createQuery(query).getResultList();
for(Object[] object : results){
System.out.println(object[0] + " " + object[1]);
}
}
通过信息...使用 Spring Boot 1.5.1 和所有默认的 JPA、Hibernate 等。
JPA 专家可以提供一些帮助吗?谢谢!
【问题讨论】:
-
你能分享
User和UserGroup实体吗? -
编辑答案以包含它们