当前位置: 首页 > 知识库问答 >
问题:

Spring数据JPA:使用联接表进行排序和分页

云昊阳
2023-03-14

我有一个场景,我想过滤、排序和分页3个表参与的结果。

目前,我使用Spring Data JPA的规范特性在单个实体上完成它:<代码>存储库。findAll(规范,页面请求)。

这工作得很好,但现在我有另一个场景,其中排序/过滤器属性分布在由一对多关系连接的3个表上。

以下是我的场景:

@Entity
public class CustomerEntity ... {
  ...

  @Column(nullable = false)
  public String                                 customerNumber;

  @OneToMany(mappedBy = "customer", cascade = CascadeType.ALL, orphanRemoval = true)
  public List<CustomerItemEntity> items;
}


@Entity
public class CustomerItemEntity ... {
  ...

  @Column(nullable = false)
  public String                                 itemNumber;

  @ManyToOne(optional = false)
  @JoinColumn(name = "customerId")
  public CustomerEntity customer;

  @OneToMany(mappedBy = "item", cascade = CascadeType.ALL, orphanRemoval = true)
  public List<DocumentEntity> documents;
}


@Entity
public class DocumentEntity ... {
  ...

  @Column(nullable = false)
  public LocalDate                                 validDate;

  @ManyToOne(optional = false)
  @JoinColumn(name = "itemId")
  public CustomerItemEntity item;
}

有没有一种方法可以使用PageRequest和Specification,其中customerNumber、itemNumber和validDate同时用于过滤、排序和分页?

共有2个答案

许毅
2023-03-14

我发现您可以通过使用可以使用自定义查询创建的连接别名按OneTo多列的内容进行排序。在存储库中,我的代码是:

@Query("select p from Person p join p.roles r")
Page<Person> search(Pageable pageable);

因此,我可以使用:

r.role

控制器通过使用:

@PageableDefault(size = 15, sort = "r.role") Pageable pageable
丁安宜
2023-03-14

尝试以下操作:

Specification<CustomerEntity> joins = (customer, query, cb) ->  {
    // from CustomerEntity c
    // join c.items i
    Join<CustomerEntity, CustomerItemEntity> items = customer.join("items");

    // join i.documents d
    Join<CustomerItemEntity, DocumentEntity> documents = items.join("documents");

    // // where c.customerNumber = ?1 and i.itemNumber = ?2 and d.validDate = ?3 
    return cb.and( 
            customer.equal(customer.get("customerNumber", customerNumber)),
            items.equal(items.get("itemNumber", itemNumber)), 
            documents.equal(documents.get("validDate", validDate))
    );
};

// sort by c.customerNumber asc
PageRequest pageRequest = new PageRequest(0, 2, new Sort(Sort.Direction.ASC, "customerNumber"));

Page<CustomerEntity> customerPage = CustomerRepo.findAll(joins, pageRequest);

但我不知道你为什么需要这里的规格?

您可以使相同的操作更加简单:

@Query("select c from CustomerEntity c join c.items i join i.documents d where c.customerNumber = ?1 and i.itemNumber = ?2 and d.validDate = ?3")
Page<CustomerEntity> getCustomers(String customerNumber, String itemNumber, LocaleDate validDate, Pageable pageable);  

但所有这些都没有意义,因为你的三个实体有顺序的一对多关联。在这种情况下,您只能使用最后一个条件,而不是三个条件:其中d.validDate=?1。然后,查询方法变得更加简单:

@Query("select c from CustomerEntity c join c.items i join i.documents d where d.validDate = ?1")
Page<CustomerEntity> getCustomers(LocaleDate validDate, Pageable pageable);

更新

要按加入实体的字段添加排序,我们可以使用查询orderBy方法:

Specification<CustomerEntity> joins = (customer, query, cb) ->  {

    Join<CustomerEntity, CustomerItemEntity> items = customer.join("items");
    Join<CustomerItemEntity, DocumentEntity> documents = items.join("documents");

    // Ascending order by 'Document.itemNumber'
    query.orderBy(cb.asc(documents.get("itemNumber")));

    return cb.and( 
            customer.equal(customer.get("customerNumber", customerNumber)),
            items.equal(items.get("itemNumber", itemNumber)), 
            documents.equal(documents.get("validDate", validDate))
    );
};

Page<CustomerEntity> customerPage = CustomerRepo.findAll(joins, new PageRequest(0, 2));

要按多个参数进行排序,可以将它们传递给用逗号或列表分隔的方法:

query.orderBy(cb.asc(items.get("customerNumber")), cb.desc(documents.get("itemNumber")));
 类似资料:
  • 本文向大家介绍Spring Data JPA进行数据分页与排序的方法,包括了Spring Data JPA进行数据分页与排序的方法的使用技巧和注意事项,需要的朋友参考一下 一、导读 如果一次性加载成千上万的列表数据,在网页上显示将十分的耗时,用户体验不好。所以处理较大数据查询结果展现的时候,分页查询是必不可少的。分页查询必然伴随着一定的排序规则,否则分页数据的状态很难控制,导致用户可能在不同的页看

  • 分页 使用 limit 和 offset 来控制分页数据: limit 指定该请求返回的结果个数 offset 偏移量,指定该请求返回的结果的起始位置 默认 limit 为 20, offset 为 0,我们也可以手动指定 limit 和 offset 来控制。例如,每页展示 100 条数据,需要获取第五页的数据,将 limit 设置为 100、offset 设置为 400 即可。limit 最大

  • {% tabs first=”SDK 1.1.0 及以上版本”, second=”SDK 1.1.0 以下版本” %} {% content “first” %} SDK 1.1.0 及以上版本 分页 使用 limit 和 offset 来控制分页数据: limit 指定该请求返回的结果个数 offset 偏移量,指定该请求返回的结果的起始位置 默认 limit 为 20, offset 为 0,

  • 我使用了spring boot(1.3.5)、spring-data、spring-data-jpa、JPA(hibernate/hsqldb)。 代码: 控制器: 我试着 也是,但不起作用。 浏览器输出: SQL无效!额外的“:”和重复的“ASC ASC”。 控制台输出:

  • 我有一个带有spring Boot(v2.3.3)和spring数据的spring web应用程序。我的评估表包含以下列: Id 我的用例是表中名称和地址的任何更改评估应该创建一个新行,版本以相同的id递增。 因此,基本上只有当地址或姓名更新时,才能在评估表中插入新记录。下面是一个示例: 现有记录: 例如,名称已更新为Ryan,应该有两行,如下所示: 因此,基本上,任何名称和地址的变化都应在评估表

  • 此外,应该对每个邮件的收件人进行排序--如果有多个类型为MessageOwnerType.to的messageOwner,那么应该按字母顺序选择第一个作为邮件的排序值。 在纯SQL中,我可能会使用某种子查询来完成此操作。使用Spring数据规范&Sort Object有类似的可能吗?除非迫不得已,否则我宁愿不必重写QueryDSL/RAW标准中的所有内容。