带有 OrderBy 和 MaxResult 的 CriteriaQuery 仅返回非 NULL 行

Posted

技术标签:

【中文标题】带有 OrderBy 和 MaxResult 的 CriteriaQuery 仅返回非 NULL 行【英文标题】:CriteriaQuery with OrderBy and MaxResult returns only non NULL rows 【发布时间】:2019-10-27 11:58:48 【问题描述】:

我有一个实体表,我想通过 CriteriaQuery.orderBy 进行排序,并使用 setFirstResult 和 setMaxResults 限制结果。 orderBy 位于连接属性上。如果有 200 个项目并且我 setMaxResults(100) 则只返回具有非 NULL 值的行。

例如,假设我有 200 个 Group 行,其中 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<>();

    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

【问题讨论】:

【参考方案1】:

在加入 Group 和 Role 实体时,您应该指定 LEFT JOIN 作为加入类型。

Join<Group, Role> join = root.join("roles", JoinType.LEFT);

【讨论】:

是的,这解决了我的问题!谢谢!

以上是关于带有 OrderBy 和 MaxResult 的 CriteriaQuery 仅返回非 NULL 行的主要内容,如果未能解决你的问题,请参考以下文章

Symfony 学说 DQL 随机结果在使用 MaxResult 的查询中

子数组的最大累加和

Leetcode最大子序和

带有瑞典字母的 OrderBy

带有别名的 SUM() 字段上的学说 orderBy

分页算法