I am using Spring data jpa in the backend codes. I have included entities, dto interfaces, service and jpa repository codes.
Now the issue is that when I call getAllTopics()
in the TopicService
. It returns a list of Topic
object instead of TopicDto
. Topic
object includes a list of examples
which I do not include in the TopicDto
. And Topic
object also includes a list of Comment
object instead of CommentDto
.
This only happens when I add Set<CommentDto> getComments()
in TopicDto
. If I remove it, everything work fine. Can anyone tell me how should I map the dto in my service and repository class? Why does it return entity class instead of dto?
@Entity @Table(name = "TOPIC") @Data @NoArgsConstructor @AllArgsConstructor public class Topic implements Serializable { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Long id; @OneToMany( fetch = FetchType.LAZY, cascade = CascadeType.REMOVE, mappedBy = "topic" ) private Set<Comment> comments= new HashSet<>(); @OneToMany( fetch = FetchType.LAZY, cascade = CascadeType.REMOVE, mappedBy = "topic" ) private Set<Example> examples = new HashSet<>(); }
@Entity @Table(name = "COMMENT") @Data @NoArgsConstructor @AllArgsConstructor public class Comment implements Serializable { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "Topic_ID") private Topic topic; @OneToMany( fetch = FetchType.LAZY, cascade = CascadeType.REMOVE, mappedBy = "comment" ) private Set<AnotherExample> anotherExamples = new HashSet<>(); }
public interface TopicDto{ Long getId(); Set<CommentDto> getComments(); }
public interface CommentDto{ Long getId(); }
public interface TopicRepository extends JpaRepository<Topic, Long> { List<TopicDto> findAllBy(Sort sort); }
@Service @Transactional public class TopicService { private final TopicRepository topicRepository ; public TopicService(TopicRepository topicRepository ) { this.topicRepository = topicRepository ; } @Transactional(readOnly = true) public List<TopicDto> getAllTopics(Sort sort) { List<TopicDto> l = topicRepository.findAllBy(sort); return l; } }
Advertisement
Answer
First thing is to change your TopicRepository
to use Topic
, the actual entity, and not TopicDto
:
public interface TopicRepository extends JpaRepository<Topic, Long> { List<Topic> findAllBy(Sort sort); }
Then, you need the following DTO classes:
import java.util.HashSet; import java.util.Set; public class TopicDto { private Long id; private Set<CommentDto> comments= new HashSet<>(); public TopicDto(Long id, Set<CommentDto> comments) { this.id = id; this.comments = comments; } }
public class CommentDto { private Long id; public CommentDto(Long id) { this.id = id; } }
Finally, in your TopicService
you need to do the mapping from Topic
to TopicDto
as follows:
@Service @Transactional public class TopicService { private final TopicRepository topicRepository ; public TopicService(TopicRepository topicRepository ) { this.topicRepository = topicRepository ; } @Transactional(readOnly = true) public List<TopicDto> getAllTopics(Sort sort) { List<Topic> topics = topicRepository.findAllBy(sort); return topics.stream() .map(topic -> { Set<CommentDto> commentsDto = topic.getComments().stream() .map(comment -> new CommentDto(comment.getId())) .collect(Collectors.toSet()); return new TopicDto(topic.getId(), commentsDto); }) .collect(Collectors.toList()); } }