jpa标准按子字段排序

yftpprvb  于 2021-07-13  发布在  Java
关注(0)|答案(1)|浏览(674)

我有三个实体。客户、流程和文件。
一个客户有很多流程,一个流程有很多文档。
我想按文档的更新日期对客户进行排序。
我的实体如下;
顾客;

  1. @Entity
  2. public class Customer {
  3. @Id
  4. @GeneratedValue(strategy = GenerationType.IDENTITY)
  5. private Long id;
  6. private String name;
  7. @OneToMany(mappedBy = "customer", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
  8. private List<Process> processes = new ArrayList<>();
  9. // getter, setter etc.
  10. }

过程;

  1. @Entity
  2. public class Process {
  3. @Id
  4. @GeneratedValue(strategy = GenerationType.IDENTITY)
  5. private Long id;
  6. private String type;
  7. @ManyToOne(fetch = FetchType.LAZY)
  8. private Customer customer;
  9. @OneToMany(mappedBy = "process", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
  10. private List<Document> documents = new ArrayList<>();
  11. //getter, setter etc.
  12. }

文件;

  1. @Entity
  2. public class Document {
  3. @Id
  4. @GeneratedValue(strategy = GenerationType.IDENTITY)
  5. private Long id;
  6. private String note;
  7. private LocalDateTime updateDate;
  8. @ManyToOne(fetch = FetchType.LAZY)
  9. private Process process;
  10. }

我试过那种规格;

  1. public static Specification<Customer> orderByDocumentUploadDate() {
  2. return (root, query, criteriaBuilder) -> {
  3. ListJoin<Customer, Process> processJoin = root.join(Customer_.processes);
  4. ListJoin<Process, Document> documentJoin = processJoin.join(Process_.documents);
  5. query.orderBy(criteriaBuilder.desc(documentJoin.get(Document_.updateDate)));
  6. query.distinct(true);
  7. return null;
  8. };
  9. }

它给出了错误;
错误:对于select distinct,order by表达式必须出现在选择列表中
生成sql;

  1. select distinct customer0_.id as id1_0_,
  2. customer0_.name as name2_0_
  3. from customer customer0_
  4. inner join
  5. process processes1_ on customer0_.id = processes1_.customer_id
  6. inner join
  7. document documents2_ on processes1_.id = documents2_.process_id
  8. order by documents2_.update_date desc
  9. limit ?

我也尝试过分组。如下图所示;

  1. public static Specification<Customer> orderByDocumentUploadDate() {
  2. return (root, query, criteriaBuilder) -> {
  3. ListJoin<Customer, Process> processJoin = root.join(Customer_.processes);
  4. ListJoin<Process, Document> documentJoin = processJoin.join(Process_.documents);
  5. query.orderBy(criteriaBuilder.desc(documentJoin.get(Document_.updateDate)));
  6. query.groupBy(root.get(Customer_.id));
  7. return null;
  8. };
  9. }

比它给的错误;
错误:列“documents2\u0.update\u date”必须出现在group by子句中或在聚合函数中使用
并生成sql;

  1. select
  2. customer0_.id as id1_0_,
  3. customer0_.name as name2_0_
  4. from
  5. customer customer0_
  6. inner join
  7. process processes1_
  8. on customer0_.id=processes1_.customer_id
  9. inner join
  10. document documents2_
  11. on processes1_.id=documents2_.process_id
  12. group by
  13. customer0_.id
  14. order by
  15. documents2_.update_date desc limit ?

我可以用那个sql来做;max()在sql中解决了这个问题

  1. select customer.* from customer
  2. inner join process p on customer.id = p.customer_id
  3. inner join document d on p.id = d.process_id
  4. group by customer.id
  5. order by max(d.update_date);

但是我不能通过criteriaapi来模拟它。
我怎样才能解决那个问题?你有什么建议吗?

ql3eal8s

ql3eal8s1#

这是一个概念上的误解。
首先,你必须了解内在是如何与工作者结合的。在这种情况下这部分是可以的[加入 process 带的表格 document 表基于 document.process_id = process.id ]
其次,您需要根据文档的更新日期对客户进行排序。
不幸的是,你用 group by 在这里。 GROUP BY 只返回它所在的列 grouped by “在这种情况下,它只会返回 customer id .
此外,还可以使用聚合函数,如count()、sum()。。。在分组数据上。
所以,当你试图进入 update_date ,它将通过下面的错误。

  1. ERROR: column "documents2_.update_date" must appear in the GROUP BY clause or be used in an aggregate function

现在我们怎样才能骑上它:
因此,首先我们需要加入以获取客户id。在获取客户id之后,我们应该根据客户id对数据进行分组,然后使用max()获取每个组的max\u日期(如果需要,则使用minimum)

  1. SELECT
  2. customer_id,
  3. max(date) AS max_date
  4. FROM
  5. document
  6. JOIN process ON process.id = document.process_id
  7. GROUP BY customer_id

它将返回一个临时表,如下所示:
客户编号:12020-10-2422021-03-1532020-09-2442020-03-15
使用临时表,您现在可以按日期对customer\u id进行排序

  1. SELECT
  2. customer_id,
  3. max_date
  4. FROM
  5. (SELECT
  6. customer_id,
  7. max(date) AS max_date
  8. FROM
  9. document
  10. JOIN process ON process.id = document.process_id
  11. GROUP BY customer_id) AS pd
  12. ORDER BY max_date DESC
展开查看全部

相关问题