使用复杂DTO管理复杂查询的最佳方法

问题描述 投票:0回答:2

我正在使用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管理复杂和动态查询(来自用户输入等的过滤器)的最佳方法是什么?

hibernate spring-boot jpa spring-data-jpa dto
2个回答
0
投票

我不赞成这样的说法,即创建实体要比直接使用DTO更快。在创建DTO之前,JPA仍必须提供中间表示。即使速度更快或使用较少的内存,问题仍然是:是否相关?


0
投票

获取实体,然后创建DTO通常是浪费,因为实体通常具有比您实际需要的多得多的列。如果您在某处使用急切的访存,那么您还将进行不必要的联接。如果您要获取嵌套的集合或复杂的表达式,请签出Blaze-Persistence Entity-Views,这是一个在JPA之上运行的库,可让您将任意结构映射到实体模型。它使您可以将预测与业务逻辑脱钩,即可以将DTO应用于现有查询。您的用例的实体视图可能如下所示

© www.soinside.com 2019 - 2024. All rights reserved.