Spring 引导:使用 ModelMapper 在 DTO 和实体之间自定义映射
Spring boot: Custom mapping between DTO and Entity using ModelMapper
我想将我的 DTO (CreateOrUpdatePostRequest
) 映射到我的实体 Post
。
但我不确定如何去做,因为我的实体有这样的关系:
@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);
}
一个post可以有一个类别和多个标签。
这是我的 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());
}
}
问题:我的问题是我必须对某些属性应用特定的映射逻辑以确保标签有效,例如:
post.setTags(tagService.findAllByIds(request.getTagIds()));
所以我想映射应该在我的 PostService
中完成,因为我知道我必须访问 tagService
?我的意思是我无法在 CreateOrUpdateRequest
.
中真正创建 toEntity
方法
有没有办法保留所有属性的默认 ModelMapper 行为,但使用外部服务为某些属性指定特定行为?
如果我的 DTO 内部有一个需要上述相同行为的 DTO,例如在 TagDTO
?
中,如何继续
我不确定你是否已经了解了 MapStruct 的东西,但你可以在这里详细查看。
https://medium.com/uphill-engineering-design/deep-dive-into-mapstruct-spring-7ddd8dac3d6d
这是基于边缘的意见,但我对此的看法仍然是:
- 我猜你的
PostService
是一个 Spring 管理的 Bean(可能用 @Service
注释),所以我想说映射应该在那里完成,使用 TagService
得到 Tag
s.
- 我不是任何映射器库的忠实粉丝,只是因为一旦使用 Spring 你的代码中就已经有足够的魔力了。话虽如此,我更喜欢明确地自己映射模型。这样做时你有充分的灵活性。
- 我会说
TagDto
应该由 TagService
映射。
我想将我的 DTO (CreateOrUpdatePostRequest
) 映射到我的实体 Post
。
但我不确定如何去做,因为我的实体有这样的关系:
@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);
}
一个post可以有一个类别和多个标签。
这是我的 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());
}
}
问题:我的问题是我必须对某些属性应用特定的映射逻辑以确保标签有效,例如:
post.setTags(tagService.findAllByIds(request.getTagIds()));
所以我想映射应该在我的
中真正创建PostService
中完成,因为我知道我必须访问tagService
?我的意思是我无法在CreateOrUpdateRequest
.toEntity
方法有没有办法保留所有属性的默认 ModelMapper 行为,但使用外部服务为某些属性指定特定行为?
如果我的 DTO 内部有一个需要上述相同行为的 DTO,例如在
中,如何继续TagDTO
?
我不确定你是否已经了解了 MapStruct 的东西,但你可以在这里详细查看。
https://medium.com/uphill-engineering-design/deep-dive-into-mapstruct-spring-7ddd8dac3d6d
这是基于边缘的意见,但我对此的看法仍然是:
- 我猜你的
PostService
是一个 Spring 管理的 Bean(可能用@Service
注释),所以我想说映射应该在那里完成,使用TagService
得到Tag
s. - 我不是任何映射器库的忠实粉丝,只是因为一旦使用 Spring 你的代码中就已经有足够的魔力了。话虽如此,我更喜欢明确地自己映射模型。这样做时你有充分的灵活性。
- 我会说
TagDto
应该由TagService
映射。