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

管理具有复杂DTO的复杂查询的最佳方法

鲜于煜祺
2023-03-14

我使用Spring JPA规范来创建标准查询。我的代码如下所示:

 public CollectionWrapper<OrderTableItemDto> getOrders(Integer page,
                                         Integer size,
                                         String search,
                                         OrderShow show) {

    Pageable pageable = PageRequest.of(page, size, Sort.by(OrderEntity_.ID).descending());

    try {
        Specification<OrderEntity> specifications = buildOrderSpecification(show, search);
        Page<OrderEntity> orders = orderDao.findAll(specifications, pageable);

        List<OrderTableItemDto> result = orders.getContent().stream().map(order -> {
            OrderTableItemDto orderTableItemDto = new OrderTableItemDto();
            orderTableItemDto.setCreatedDate(order.getCreatedDate());
            orderTableItemDto.setCustomerId(order.getCustomer().getId());
            orderTableItemDto.setId(order.getId());
            orderTableItemDto.setStatus(order.getStatus());
            orderTableItemDto.setTotalCost(order.getTotalCost());
            orderTableItemDto.setOrderType(order.getOrderType());
            orderTableItemDto.setOrderTypeLabel(order.getOrderType().getLabel());
            if(order.getOrderInShippingMethod() != null) {
                orderTableItemDto.setShipped(OrderShippingStatus.DELIVERED.equals(order.getOrderInShippingMethod().getStatus()));
            } else {
                orderTableItemDto.setShipped(false);
            }
            StringBuilder sb = new StringBuilder();
            sb.append("#")
                    .append(order.getId())
                    .append(" ");
            if(order.getOrderType().equals(OrderType.WEB_STORE)) {
                sb
                        .append(order.getBilling().getFirstName())
                        .append(" ")
                        .append(order.getBilling().getLastName());

            } else {
                sb.append(order.getCustomer().getFullName());
            }

            orderTableItemDto.setTitle(sb.toString());
            return orderTableItemDto;
        }).collect(Collectors.toList());
        return new CollectionWrapper<>(result, orders.getTotalElements());

我被告知这是一种糟糕的方法,我应该使用投影(DTO)从数据库中读取,因为创建实体并在之后映射它们很昂贵。问题是我不知道如何将规范与DTO相结合。要使用包含嵌套 DTO 和大量属性的复杂 DTO 来管理复杂和动态查询(来自用户输入的筛选器等)的最佳方式是什么?

共有1个答案

阎成天
2023-03-14

我不认为创建实体比直接使用DTO更快。在创建 DTO 之前,JPA 仍必须提供中间表示形式。即使它更快或使用更少的内存,问题仍然是:它是否相关?

如果性能是此代码更改的原因,您应该做的第一件事是实现适当的基准测试。请参阅如何从JUnit测试中运行JMH?

您经常有各种选项来创建DTO。

使用派生查询(基于方法名称的查询)或基于@Query注释,您可以使用基于类的 DTO,即看起来像实体但可能具有较少属性的类。或者,您可以使用只有您感兴趣的值的 getter 的接口。在这两种情况下,您都可以将返回类型替换为投影。请参阅 https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections

如果您使用的是 JPQL 或条件 API,则可以使用构造函数表达式。例如,请参阅此答案的示例:https://stackoverflow.com/a/12286281/66686

当然,当您在这个级别上进行调优时,您应该考虑JPA是否在浪费性能,并将其与更直接在数据库上工作的东西进行比较,例如< code>JdbcTemplate、Querydsl或jOOQ。

 类似资料:
  • 我有2个实体(这只是一个简化的例子,不是真正的实体): 当我尝试使用order By编写查询时,Hibernate崩溃: 原因:java.sql.SqlSyntaxerRoreXception:ORA-01791:不是选定的表达式

  • 我有一个服务方法: 在对jpa存储库(findAll)的第一次调用中,结果长度为 最后的dto是: 列表结果列表=新的ArrayList()// 每个对象都有列表EntityList// 服务响应时间为10-15秒。。。 有没有减少服务时间的最佳方法?如果我使用Oracle表视图或递归查询而不是Java? 谢谢你的回复

  • 问题内容: 如何查询具有复杂类型(如地图/数组)的RDD?例如,当我编写此测试代码时: 我认为语法应该是这样的: 或者 但是我明白了 无法访问类型为MapType(StringType,StringType,true)的嵌套字段 和 org.apache.spark.sql.catalyst.errors.package $ TreeNodeException:无法解析的属性 分别。 问题答案:

  • 我有这个: 如何从hashlist中排除“item”?打破了我的头。Linq不想对我开放。

  • 问题内容: 我正在尝试查询Google BigQuery公共Reddit数据集。我的目标是使用Jaccards’Index来计算子reddit的相似性,该索引的定义如下: 我的计划是在2016年8月按评论数选择前N = 1000个子项,然后计算其笛卡尔积,以得到形状中所有子项的组合。 然后使用这些组合的行来查询subreddit1和subreddit 2之间的用户并集以及交集。 我到目前为止的查询

  • 问题内容: 表Words_Learned包含用户已知的所有单词以及 单词学习的顺序。它具有3列:1)单词ID和2)用户ID,以及3) 单词学习的顺序。 表中Article包含文章。它具有3列:1)文章ID,2) 唯一字数和3)文章内容。 该表Words包含每篇文章中包含的所有唯一单词的列表。 它有2列1)单词ID和2)文章ID 数据库图如下/ 在此处输入图片说明 您可以从此处下载数据库代码:htt