我有一个实体表,我想通过CriteriaQuery.orderBy进行排序,并使用setFirstResult和setMaxResults限制结果。 orderBy位于联接的属性上。如果说有200个项目,并且我设置了setMaxResults(100),则仅返回具有非NULL值的行。
例如,假设我有200个“组”行,而50个有“ Group.roles”值,其余的则没有值。如果我将setMaxResults(100)退回50。这打破了Vaadin框架,该框架从更高级别的代码调用此查询,因为它知道(通过单独的查询)有200个条目,但仅返回100个条目,因此它重复运行同一查询以尝试获得所有200个条目。
这是我的大概代码:
@Entity()
@Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "ID" }) }, name = "T_Group")
public class Group {
@Basic()
@Column(name = "Name")
private String name = null;
@ManyToMany(cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH }, fetch = FetchType.EAGER)
@JoinTable(joinColumns = { @JoinColumn(name = "Group_id") }, inverseJoinColumns = {
@JoinColumn(name = "Role_id") }, name = "Group_Roles")
private List<Role> roles = new ArrayList<Role>();
}
@Entity()
@Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "Name" }),
@UniqueConstraint(columnNames = { "iD" }) }, name = "T_Role")
public class Role {
@Basic()
@Column(name = "ID")
private String iD = null;
@Basic()
@Column(name = "Name")
private String name = null;
}
public List<Group> query() {
String property = "roles";
int offset = 0;
int limit = 100;
boolean ascending = false;
EntityManager em = ...;
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<?> criteriaQuery = builder.createQuery(CertificatePolicy.class);
Root<CertificatePolicy> root = criteriaQuery.from(CertificatePolicy.class);
List<Order> orders = new ArrayList<>();
Root<Group> root = context.getRoot();
Join<Group, Role> join = root.join("roles");
Expression<?> path = join.get("name");
orders.add( ascending ? builder.asc(path) ? builder.desc(path) );
criteriaQuery.select(root);
criteriaQuery.orderBy(orders);
List<CertificatePolicy> items = em.createQuery(criteriaQuery)
.setFirstResult(offset).setMaxResults(limit).getResultlList();
return items;
}
使用休眠5.4.3.Final
答案 0 :(得分:1)
在加入组和角色实体时,应指定LEFT JOIN作为加入类型。
Join<Group, Role> join = root.join("roles", JoinType.LEFT);