1

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?

1
  • Just create class/service which will convert your dto to entity or add a function inside entity which can create this entity based on DTO (maybe something like builder class or something) Commented Nov 17, 2021 at 13:57

2 Answers 2

4

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

Sign up to request clarification or add additional context in comments.

9 Comments

I have to study all this knowing that I am doing this on a very large entity. Where do you store your mappers in your code? I'm talking about code organization. In a new Mapper package ?
yes, they can have their own package
Ok thanks. If I understand correctly MapStruct relies on interfaces to generate the class that will convert my DTO into an entity. So I can hardly have a specific behavior like my example with services?
yes, but you can override the behavior whichever way you want, you will find it in the article I shared
Yes, I saw the link. But can I for example use the same MapStruct for adding an entity for example and the same but ignoring null properties for updating an entity for example. I'm trying to do a CRUD.
|
0

This is borderline opinion-based, but still here is my take on this:

  1. I guess that your PostService is a Spring-managed Bean (possibly annotated with @Service), so I would say the mapping should be done there, using TagService to get the Tags.
  2. I am not a big fan of any mapper library, simply because once using Spring you have already enough magic going around in your code. Having said that, I much more prefer to be explicit and map the models on my own. You have full flexibility while doing so.
  3. I would say that TagDto should be mapped by the TagService.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.