Search code examples
javaspringmodelmapper

Spring boot: Custom mapping between DTO and Entity using ModelMapper


I would like to map my DTO (CreateOrUpdatePostRequest) to my entity Post.

But I'm not sure how to go about it since my entity has relationships like this:

@Entity
@Table(name = "POSTS")
@Data
public class Post {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "post_id")
    private int id;

    private String title;

    private String description;

    @Temporal(TemporalType.DATE)
    @Column(name = "expire_at")
    private Calendar expireAt;

    @ManyToOne
    @JoinColumn(name = "CATEGORY_ID")
    private Category category;

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "TAG_POST", joinColumns = { 
            @JoinColumn(name = "post_id", nullable = false, updatable = false) }, 
            inverseJoinColumns = { @JoinColumn(name = "tag_id", 
                    nullable = false, updatable = false) })
    private Set<Tag> tags = new HashSet<Tag>(0);
}

A post can have one category and several tags.

And here is my DTO :

@Data
public class CreateOrUpdatePostRequest {
    @NotNull
    @Size(min = 10, max = 30)
    private Sting title;

    @NotNull
    @Size(min = 50, max = 600)
    private String description

    @NotNull
    @ValidDateString
    private String expireAt;

    @NotNull
    private Category category;

    @NotNull
    private List<TagDTO> tags;

    public List<Integer> getTagIds() {
        return this.getTags().stream().map(TagDTO::getId).collect(Collectors.toList());
    }
}

Problem: My problem is that I have to apply a particular mapping logic for some properties to make sure that the tags are valid for example:

post.setTags(tagService.findAllByIds(request.getTagIds()));
  1. So I guess the mapping should be done in my PostService knowing that I have to access the tagService? What I mean is that I can't really create a toEntity method in my CreateOrUpdateRequest.

  2. Is there a way to leave the default ModelMapper behavior for all properties, but specify specific behavior using an external service for certain properties?

  3. How to proceed if for example my DTO has a DTO inside that needs the same behavior described above, for example in a TagDTO?


Solution

  • I am not sure whether you have already gone through MapStruct thing, but you can look at it here in detail.

    https://medium.com/uphill-engineering-design/deep-dive-into-mapstruct-spring-7ddd8dac3d6d