Entities
实体必须实现Identifiable接口。例如:
@Entitypublic class Category implements Identifiable<Integer> { @Id @GeneratedValue private final Integer id; private final String name; @oneToMany private final Set<Product> products = new HashSet<>(); // skipped}@Entitypublic class Product implements Identifiable<Integer> { @Id @GeneratedValue private final Integer id; private final String name; // skipped}
Projections
public interface CategoryProjection { Category getCategory(); Long getQuantity();}
这将是DTO的基础。在此示例中,DTO将代表a Category,而
Products的数量属于它。
Repository methods
Create方法将返回投影:一个投影,一个DTO列表和一个DTO页面列表。
@RepositoryRestResourcepublic 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
从其接口实施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其中添加自定义方法将满足DTO的请求:
@RepositoryRestController@RequestMapping("/categories")public class CategoryController { @Autowired private CategoryRepo repo; @Autowired private RepositoryEntitylinks links; @Autowired private PagedResourcesAssembler<CategoryProjection> assembler; @GetMapping("/{id}/dto") public ResponseEntity<?> getDto(@PathVariable("id") Integer categoryId) { CategoryProjection dto = repo.getDto(categoryId); return ResponseEntity.ok(toResource(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)); } @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使用该对象及其链接创建一个新的。
Result
请参阅Postman网站上的API文档
Singe 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" } }}
List of 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" } }}
Paged list of 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 }}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)