【问题标题】:Server side sorting for calculated fields with pagination?带有分页的计算字段的服务器端排序?
【发布时间】:2020-05-04 08:47:51
【问题描述】:

我们必须显示一些支持分页和服务器端排序的表格数据。 它是一个 React、JAVA、SQL 堆栈。 在设计 REST API 时,我们同意返回一个复合对象,表示 桌子。该对象是由具有大量业务逻辑的复杂 SQL 创建的。 该对象包括多个对象,每个对象包括多个字段。这背后的想法是 返回一个通用对象,这样我们就不必创建请求特定的 DTO。

然而,我们只需要使用这个对象的几个字段。 UI 上显示的几列 基于此对象中的多个字段计算。 真正的挑战是当我们必须在服务器端对这些计算字段进行排序时,因为我们只获取必须在页面上显示的记录。 我们很想通过在服务器端进行计算来重构响应以匹配 UI 列,因为我们会遇到多个 DTO 问题。 如何以最好的方式实现这一目标?有没有这方面的最佳实践?我在互联网上找不到太多内容。

【问题讨论】:

  • 正常的解决方法是将排序字段作为查询参数包含在内,然后服务器可以将这些字段传递给 SQL 查询(带有限制/偏移量)以根据需要处理分页。
  • 这是我最初的想法。然而,计算并不是直截了当的。如果我们在前端计算字段,为了在服务器端对其进行排序,相同的计算将不得不在服务器端(SQL)上重复相同的字段
  • 满足您的需求的好方法是使用 GraphQL 而不是 DTO。 graphql.org/learn/queries。这是另一个示例:graphql-java.com/tutorials/getting-started-with-spring-boot。使用这种方法,您可以在服务器端对这些计算字段进行排序,而无需多个 DTO。

标签: java sql rest sorting pagination


【解决方案1】:

你用什么来序列化对 JSON 的响应?

如果您使用的是 Jackson,我建议您使用 JSON 视图以避免使用多个 DTO。它允许您指定要在哪种情况下序列化哪些字段(大多数情况下由控制器指定)并且使用起来非常简单。

这里有一个使用教程:https://www.baeldung.com/jackson-json-view-annotation

以及我如何使用它的示例(例如,带有附件类):

这是我定义哪个属性将包含在哪个视图中的模型:

public class Attachment {

    @JsonView({
        Attachment.Views.Show.class, Attachment.Views.List.class
    })
    private Long id;

    @JsonView({
        Attachment.Views.Show.class, Attachment.Views.List.class
    })
    private String originalFilename;

    @JsonView({
        Attachment.Views.Show.class
    })
    private String filepath;

    @JsonView({
        Attachment.Views.Show.class
    })
    private String description;

        public static class Views {
        public static class Show {}
        public static class List {}
        public static class Create {}
        public static class Fill {}
        public static class Edit {}
    }

}

这是我的控制器:

public class AttachmentControllerImpl implements AttachmentController {

    @Inject
    private AttachmentService service;

    private ObjectMapper mapper;

    @Override
    public Response show(Long id) {
        Attachment attachment = service.getById(id);

        String json = mapper.writerWithView(Attachment.Views.Show.class).writeObjectAsString(attachment);
    }

    @Override
    public Response list() {
        List<Attachment> attachments = service.getAll();

        String json = mapper.writerWithView(Attachment.Views.List.class).writeObjectAsString(attachments);
    }

}

真的没有比它更多的东西了,非常好用。

【讨论】:

    【解决方案2】:

    对于服务器需要进行大量处理而不是立即返回答案的类似问题,我将请求拆分为几个部分。

    1) 向服务器发送一个请求,以构建结果。它不是将结果返回给客户端,而是将结果存储在数据库中的结果表中,并与结果引用 ID 一起作为对 POST 请求的回复返回给客户端。 这些结果将包括要排序的计算字段。在将参考 ID 返回给客户端后,服务器可能会继续在后台构建这些结果。服务器应该回复 202 Accepted 响应,而不是 201 Created。

    2) 向服务器发送请求以查询此结果表,并传递参考 ID。包括要排序的字段。如果服务器仍在构建列表,它可以返回 OK 200,但使用描述“构建”的 JSON 结构在此期间,客户端可能会显示计时器动画,并每隔几秒重复一次请求。

    3) 最终建表时,服务器根据需要将分页数据传回。

    4) 完成后,客户端可以发送带有参考 ID 的 DELETE 来清理结果表。但是,应该有某种清理过程来清理超过一天的结果。

    更多信息请看这里:https://farazdagi.com/2014/rest-and-long-running-jobs/

    也在这里: http://restcookbook.com/Resources/asynchroneous-operations/

    【讨论】:

      猜你喜欢
      • 2013-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-26
      • 1970-01-01
      • 2020-05-09
      相关资源
      最近更新 更多