[英]Force MapStruct to use custom method instead of dto value
I have a UserDTO and User entity which I want to map. 我有一个要映射的UserDTO和User实体。 When creating a new User some fields (for example: password
, modifiedBy
) must be generated by some custom method (for example: password
is randomly generated and encoded, but modifiedBy
username is retrieved from security service). 创建新用户时,必须通过某些自定义方法来生成某些字段(例如: password
, modifiedBy
)(例如: password
是随机生成和编码的,但是从安全服务中检索了modifiedBy
用户名)。 For this I autowire some services into the mapper. 为此,我将一些服务自动连接到了映射器中。 Many of them return String
and MapStruct cannot understand which one to use in each case and just uses the first it found on everything that accepts String
as input. 它们中的许多返回String
而MapStruct无法理解在每种情况下都使用哪个,而仅使用在接受String
作为输入的所有内容上找到的第一个。
@Mapper(componentModel = "spring", uses = PasswordEncoder.class)
public interface UserMapper {
@Mapping(target = "password", qualifiedByName = "PASS")
User mapUser(UserDto dto);
@Named("PASS")
default String getPass(PasswordEncoder passwordEncoder){
return passwordEncoder.encode(some_random_generator);
}
}
This generates code that just uses method from PasswordEncoder
in any setter that accepts String
and getPass(...)
method is not used at all. 这会生成仅使用接受任何String
setter中的PasswordEncoder
中的方法的代码,并且getPass(...)
不使用getPass(...)
方法。 However I need it to use my getPass(...)
method on password
field only. 但是我需要它仅在password
字段上使用我的getPass(...)
方法。
Currently it is not possible to pass the used mapper or service to a default method. 当前无法将使用的映射器或服务传递给默认方法。 There is mapstruct/mapstruct#1637 open for that. 为此打开了mapstruct / mapstruct#1637 。 Also you can't really do @Mapper( uses = PasswordEncoder.class )
as that would lead to all String
to String
to be mapped via the PasswordEncoder
. 另外,您实际上不能做@Mapper( uses = PasswordEncoder.class )
因为这将导致所有String
到String
都通过PasswordEncoder
映射。 What you can do though is to create your own custom PasswordEncoderMapper
and use @Named
on it, this way you would be in control. 但是,您可以做的是创建自己的自定义PasswordEncoderMapper
并在其上使用@Named
,这样您就可以控制自己。
This can look like this: 看起来可能像这样:
@Qualifier // org.mapstruct.Qualifier
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface EncodedMapping {
}
public class PasswordEncoderMapper {
protected final PasswordEncoder passwordEncoder;
public PasswordEncoderMapper(PasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
}
@EncodedMapping
public String encode(String value) {
return passwordEncoder.encode(value);
}
}
@Mapper(componentModel = "spring", uses = PasswordEncoderMapper.class)
public interface UserMapper {
@Mapping(target = "password", qualifiedBy = EncodedMapping.class)
User mapUser(UserDto dto);
}
Regarding the modifiedBy
property. 关于modifiedBy
属性。 You should do that as part of an @ObjectFactory
or by using an expression. 您应该将其作为@ObjectFactory
一部分或通过使用表达式来执行。
With an expression this can look like: 使用表达式可以看起来像:
@Mapper(componentModel = "spring", uses = PasswordEncoderMapper.class, imports = SecurityUtils.class)
public interface UserMapper {
@Mapping(target = "password", qualifiedBy = EncodedMapping.class)
@Mapping(target = "modifiedBy", expression = "java(SecurityUtils.getCurrentUserId())")
User mapUser(UserDto dto);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.