gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 01:33:17 30 4
gpt4 key购买 nike

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

最佳答案

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

工作示例是 here

实体

实体必须执行 Identifiable界面。例如:

@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
}

预测

制作 projection存储库查询方法将返回的接口(interface):

public interface CategoryProjection {

Category getCategory();
Long getQuantity();
}

这将是 DTO 的地下室。在此示例中,DTO 将表示 CategoryProduct 的数量s是属于它的。

存储库方法

Create 方法返回投影:一个、一个 DTO 列表和一个 DTO 分页列表。

@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

从其接口(interface)实现 DTO:

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

private final Category category;
private final Long quantity;

// skipped
}

注释 Relation在 Spring Data REST 渲染对象时使用。

Controller

将自定义方法添加到 RepositoryRestController这将服务于 DTO 的请求:

@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);
}
}

当从存储库接收到 Projections 时,我们必须进行从 Projection 到 DTO 的最终转换
并将其“包装”到 ResourceSupport发送给客户端之前的对象。
为此,我们使用辅助方法 toResource :我们创建一个新的 DTO,为这个对象创建必要的链接,
然后创建一个新的 Resource与对象及其链接。

结果

请参阅 Postman site 上的 API 文档

单DTO
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"
}
}
}

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
}
}

关于spring - 如何在 Spring Data REST 项目中使用 DTO?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45401734/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com