[英]Mapstruct: How to use custom mappers with @MappingTarget
我正在使用 Mapstruct,我需要使用@MappingTarget
更新现有的 bean,但需要应用一些复杂的逻辑来设置目标中的正确字段。
可以说我有一个看起来像这样的目标 bean。 用户有一个帐户列表,其中一个帐户被标记为收藏。
UserDetails {
String name;
List<Account> accounts;
}
Account {
String id;
boolean favourite;
}
DTO 类包含他们最喜欢的帐户的帐户 ID。
UserDetialsDTO {
String name;
String favouriteAccountId;
List<String> accountIds;
}
我需要使用一些复杂的逻辑来更新帐户列表中的正确Account
。
UserDetails fromDto(UserDetialsDTO dto, @MappingTarget UserDetails userDetails);
查找和更新正确Account
以使其成为收藏夹的逻辑是这样的:
userDetails.accounts
.stream()
.forEach(acct -> acct.setFavourite(dto.favouriteAccountId.equals(acct.id))) ;
我如何告诉 Mapstruct 在更新@MapingTarget
时使用此自定义逻辑?
尝试:
@Mapper
public interface MyMapper {
@Mapping( target = "accounts", ignore = true )
void fromDto(UserDetialsDTO dto, @MappingTarget UserDetails userDetails);
@AfterMapping
default void handleAccounts(UserDetialsDTO dto, @MappingTarget UserDetails userDetails) {
userDetails.accounts
.stream()
.forEach(acct -> acct.setFavourite(dto.favouriteAccountId.equals(acct.id))) ;
}
}
您可以使用装饰器来同时实现:
Account
列表初始化如:
@Mapper
@DecoratedWith(MyMapperDecorator.class)
public interface MyMapper {
void fromDto(UserDetialsDTO dto, @MappingTarget UserDetails userDetails);
}
public class MyMapperDecorator implements MyMapper{
@Override
public void fromDto(final UserDetialsDTO dto, final UserDetails userDetails) {
if(dto == null){
return;
}
dto.getAccountIds().forEach(a -> {
final Account account = new Account();
account.setId(a);
account.setFavourite(a.equals(dto.getFavouriteAccountId()));
userDetails.getAccounts().add(new Account());
});
}
}
为了避免重复,我建议使用Set<Account>
而不是List
并相应地实施Account.equals()
。
另一种(稍微)更复杂的方法可能涉及定义一个String
到Account
映射器使用它:
@Mapper(uses = AccountMapper.class)
@DecoratedWith(MyMapperDecorator.class)
interface MyMapper {
MyMapper INSTANCE = Mappers.getMapper( MyMapper.class );
@Mapping(target = "accounts", source="accountIds")
abstract void update(UserDetialsDTO dto, @MappingTarget UserDetails userDetails);
}
public abstract class MyMapperDecorator implements MyMapper{
private final MyMapper delegate;
MyMapperDecorator(final MyMapper delegate){
this.delegate = delegate;
}
@Override
public void update(final UserDetialsDTO dto, final UserDetails userDetails) {
if(dto == null){
return;
}
delegate.update(dto, userDetails);
userDetails.accounts
.stream()
.forEach(acct -> acct.setFavourite(dto.favouriteAccountId.equals(acct.id))) ;
}
}
@Mapper
public interface AccountMapper {
Account fromString(String id);
void update(String id, @MappingTarget Account account);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.