Решение
@RestController
@RequestMapping("api/read")
public class PostReadRest {
private static final String PATH_TO_READ_POST_BY_ID = "post/{id}";
private static final String PATH_TO_READ_POST_LIST = "post/list";
private PostReadService service;
@Autowired
public PostReadRest(PostReadService service) {
this.service = service;
}
@GetMapping(PATH_TO_READ_POST_BY_ID)
public PostDto getPostById(@PathVariable String id){
Long idLong = Long.valueOf(id);
return service.getEntryById(idLong);
}
}
@Service
public class PostReadServiceImpl implements PostReadService {
private PostRepository repository;
private PostTransformer transformer;
private CommentTransformer transformerComment;
@Autowired
public PostReadServiceImpl(PostRepository repository, PostTransformer transformer,
CommentTransformer transformerComment) {
this.repository = repository;
this.transformer = transformer;
this.transformerComment = transformerComment;
}
@Transactional
@Override
public PostDto getEntryById(Long id) {
Post entity = find(id);
PostDto postDto = this.transformer.transformEntityToDto(entity);
return postDto;
}
private Post find(Long id){
return this.repository.findById(id).orElseThrow(() -> new RuntimeException("Post not found!"));
}
}
@Mapper(componentModel = "spring")
public interface PostMapper {
Post postDtoToPostEntity(PostDto dto);
@Mapping(target = "post.comments", ignore = true)
CommentDto toCommentDto(Comment entity);
PostDto postEntityToPostDto(Post entity);
Iterable<Post> postListDtoToPostListEntity(Iterable<PostDto> list);
Iterable<PostDto> postListEntityToPostListDto(Iterable<Post> list);
}
- @ Mapping (target = "post.comments", ignore = true)
post - это это имя поля «Комментарий» сущности.
comments - это имя поля «Пост» сущности, но это поле здесь - поле второго уровня. И это надо игнорировать.
@Component
public class PostTransformer {
private PostMapper mapper;
@Autowired
public PostTransformer(PostMapper mapper) {
this.mapper = mapper;
}
public PostDto transformEntityToDto(Post entity){
PostDto postDto = this.mapper.postEntityToPostDto(entity);
return postDto;
}
public Post transformDtoToEntity(PostDto dto){
return this.mapper.postDtoToPostEntity(dto);
}
public Iterable<PostDto> transformListEntityToDtoList(Iterable<Post> listEntity){
Iterable<PostDto> postDtoList = this.mapper.postListEntityToPostListDto(listEntity);
return postDtoList;
}
public Iterable<Post> transformListDtoToEntityList(Iterable<PostDto> listDto){
return this.mapper.postListDtoToPostListEntity(listDto);
}
}
Результат
{
"id": 1,
"subject": "JPA Entity Graph In Action",
"comments": [
{
"id": 1,
"reply": "Nice !!",
"post": {
"id": 1,
"subject": "JPA Entity Graph In Action",
"comments": [],
"user": {
"id": 1,
"name": "user1",
"email": "user1@test.com"
}
},
"user": {
"id": 2,
"name": "user2",
"email": "user2@test.com"
}
},
{
"id": 2,
"reply": "Cool !!",
"post": {
"id": 1,
"subject": "JPA Entity Graph In Action",
"comments": [],
"user": {
"id": 1,
"name": "user1",
"email": "user1@test.com"
}
},
"user": {
"id": 3,
"name": "user3",
"email": "user3@test.com"
}
}
],
"user": {
"id": 1,
"name": "user1",
"email": "user1@test.com"
}
}
Это важно .
Если вы не указали на метод (он имеет аннотацию @Override) аннотацию @ Transactional , вы столкнетесь с Exception , если Вы используете - FetchType.LAZY
@Transactional
@Override
public PostDto getEntryById(Long id) {
Post entity = findEntry(id);
List<Comment> comments = entity.getComments();
PostDto postDto = this.transformer.transformEntityToDto(entity);
return postDto;
}
Во время выполнения транзакции, в то время как выполняется Mapper, будет выполняться дополнительный запрос, который получает вложенные записи из связанных таблиц.