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

如何在Spring Data REST项目中使用DTO?

唐炳
2023-03-14

Spring Data REST只自动公开域对象。但大多数情况下,我们必须处理数据传输对象。那么如何用SDR的方式做到这一点呢?

共有1个答案

谢唯
2023-03-14

在Spring Data REST项目中使用DTO的方法

工作示例在这里

实体

@Entity
public class Category implements Identifiable<Integer> {

    @Id
    @GeneratedValue
    private final Integer id;

    private final String name;

    @OneToMany
    private final Set<Product> products = new HashSet<>();

    // skipped
}

@Entity
public class Product implements Identifiable<Integer> {

    @Id
    @GeneratedValue
    private final Integer id;

    private final String name;

    // skipped
}
public interface CategoryProjection {

    Category getCategory();
    Long getQuantity();
}
@RepositoryRestResource
public interface CategoryRepo extends JpaRepository<Category, Integer> {

    @RestResource(exported = false)
    @Query("select c as category, count(p) as quantity from Category c join c.products p where c.id = ?1 group by c")
    CategoryProjection getDto(Integer categoryId);

    @RestResource(exported = false)
    @Query("select c as category, count(p) as quantity from Category c join c.products p group by c")
    List<CategoryProjection> getDtos();

    @RestResource(exported = false)
    @Query("select c as category, count(p) as quantity from Category c join c.products p group by c")
    Page<CategoryProjection> getDtos(Pageable pageable);
}

从其接口实现DTO:

@Relation(value = "category", collectionRelation = "categories")
public class CategoryDto implements CategoryProjection {

    private final Category category;
    private final Long quantity;

    // skipped
}

注释relation在Spring Data REST呈现对象时使用。

控制器

@RepositoryRestController
@RequestMapping("/categories")
public class CategoryController {

    @Autowired private CategoryRepo repo;
    @Autowired private RepositoryEntityLinks links;
    @Autowired private PagedResourcesAssembler<CategoryProjection> assembler;

    /**
    * Single DTO
    */
    @GetMapping("/{id}/dto")
    public ResponseEntity<?> getDto(@PathVariable("id") Integer categoryId) {
        CategoryProjection dto = repo.getDto(categoryId);

        return ResponseEntity.ok(toResource(dto));
    }

    /**
    * List of DTO
    */
    @GetMapping("/dto")
    public ResponseEntity<?> getDtos() {
        List<CategoryProjection> dtos = repo.getDtos();

        Link listSelfLink = links.linkFor(Category.class).slash("/dto").withSelfRel();
        List<?> resources = dtos.stream().map(this::toResource).collect(toList());

        return ResponseEntity.ok(new Resources<>(resources, listSelfLink));
    }

    /**
    * Paged list of DTO
    */
    @GetMapping("/dtoPaged")
    public ResponseEntity<?> getDtosPaged(Pageable pageable) {
        Page<CategoryProjection> dtos = repo.getDtos(pageable);

        Link pageSelfLink = links.linkFor(Category.class).slash("/dtoPaged").withSelfRel();
        PagedResources<?> resources = assembler.toResource(dtos, this::toResource, pageSelfLink);

        return ResponseEntity.ok(resources);
    }

    private ResourceSupport toResource(CategoryProjection projection) {
        CategoryDto dto = new CategoryDto(projection.getCategory(), projection.getQuantity());

        Link categoryLink = links.linkForSingleResource(projection.getCategory()).withRel("category");
        Link selfLink = links.linkForSingleResource(projection.getCategory()).slash("/dto").withSelfRel();

        return new Resource<>(dto, categoryLink, selfLink);
    }
}
GET http://localhost:8080/api/categories/6/dto
{
    "category": {
        "name": "category1"
    },
    "quantity": 3,
    "_links": {
        "category": {
            "href": "http://localhost:8080/api/categories/6"
        },
        "self": {
            "href": "http://localhost:8080/api/categories/6/dto"
        }
    }
}
GET http://localhost:8080/api/categories/dto
{
    "_embedded": {
        "categories": [
            {
                "category": {
                    "name": "category1"
                },
                "quantity": 3,
                "_links": {
                    "category": {
                        "href": "http://localhost:8080/api/categories/6"
                    },
                    "self": {
                        "href": "http://localhost:8080/api/categories/6/dto"
                    }
                }
            },
            {
                "category": {
                    "name": "category2"
                },
                "quantity": 2,
                "_links": {
                    "category": {
                        "href": "http://localhost:8080/api/categories/7"
                    },
                    "self": {
                        "href": "http://localhost:8080/api/categories/7/dto"
                    }
                }
            }
        ]
    },
    "_links": {
        "self": {
            "href": "http://localhost:8080/api/categories/dto"
        }
    }
}

DTO的分页列表

GET http://localhost:8080/api/categories/dtoPaged
{
    "_embedded": {
        "categories": [
            {
                "category": {
                    "name": "category1"
                },
                "quantity": 3,
                "_links": {
                    "category": {
                        "href": "http://localhost:8080/api/categories/6"
                    },
                    "self": {
                        "href": "http://localhost:8080/api/categories/6/dto"
                    }
                }
            },
            {
                "category": {
                    "name": "category2"
                },
                "quantity": 2,
                "_links": {
                    "category": {
                        "href": "http://localhost:8080/api/categories/7"
                    },
                    "self": {
                        "href": "http://localhost:8080/api/categories/7/dto"
                    }
                }
            }
        ]
    },
    "_links": {
        "self": {
            "href": "http://localhost:8080/api/categories/dtoPaged"
        }
    },
    "page": {
        "size": 20,
        "totalElements": 2,
        "totalPages": 1,
        "number": 0
    }
}
 类似资料:
  • 我之所以问这个问题,是因为我对Java和Android还不熟悉,我花了好几个小时想弄清楚这个问题。答案来自相关答案的组合,所以我想我会把我学到的东西记录下来,给其他正在挣扎的人。参见答案。 我使用的是Android Studio2.1.2,我的Java设置如下:

  • 我创建了一个NetBeans企业应用程序,它由包装ejb(jar)项目和web(war)项目的ear组成。 我的web项目中有一个servlet,我想在其中使用ejb项目中的一个ejb。

  • 问题内容: Spring Data REST仅自动公开域对象。但是大多数情况下,我们必须处理数据传输对象。那么如何以SDR方式做到这一点呢? 问题答案: Entities 实体必须实现Identifiable接口。例如: Projections 创建一个投影接口,存储库查询方法将返回: 这将是DTO的基础。在此示例中,DTO将代表a Category,而 的数量属于它。 Repository me

  • 问题内容: 有几个jar文件,这些文件来自COTS产品,我们将其保存在项目根目录下的项目“ extlib”文件夹中。我想将这些包含在常春藤中,但不要放在存储库中,只需从project / extlib文件夹中读取即可。这是可能的还是我需要将它们添加到工件中? 问题答案: 创建具有以下内容的常春藤设置文件: 并声明您的依赖项,如下所示: 特殊的“ NA”组织配置为从“ extlib”目录中提取文件。