CriteriaQuery с OrderBy и MaxResult возвращает только ненулевые строки - PullRequest
0 голосов
/ 13 июня 2019

У меня есть таблица сущностей, и я хочу отсортировать через CriteriaQuery.orderBy и ограничить результаты, используя setFirstResult и setMaxResults. OrderBy находится в объединенном атрибуте. Если есть, скажем, 200 элементов, и я setMaxResults (100), то возвращаются только те строки, которые имеют ненулевые значения.

Например, допустим, у меня есть 200 строк группы, а 50 имеют значение для Group.roles, а остальные не имеют значения. Если я установлю MaxResults (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;
}

Использование hibernate 5.4.3.Final

1 Ответ

1 голос
/ 24 июля 2019

Вы должны указать LEFT JOIN в качестве типа соединения при объединении объектов Group и Role.

Join<Group, Role> join = root.join("roles", JoinType.LEFT);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...