【问题标题】:Is it possible to map with Mapstruct an attribute of object B to attribute of object A_DTO, when object A contains a reference to object B?当对象 A 包含对对象 B 的引用时,是否可以使用 Mapstruct 将对象 B 的属性映射到对象 A_DTO 的属性?
【发布时间】:2020-08-12 08:37:47
【问题描述】:

根据 Mapstruct 文档,可以通过为引用的对象(对象 B)定义映射方法将包含另一个对象(对象 B)的对象(对象 A)映射到 DTO。但是如果我只需要映射该对象(对象 B)的属性而不是整个对象呢?

描述问题 - 我正在研究 Spring Boot,这是我的项目 - https://github.com/Alex1182-St/java-spring-jpa-postgresql

出于安全考虑,我需要将我的 AppUserEntity 映射到 AppUserDetailsDTO(实现 UserDetails),尤其是我需要将 name 从将我的 AppUserEntityprivate Set<RoleEntity> roles 属性添加到我的 AppUserDetailsDTO

private Collection<GrantedAuthority> authorities

使用 Kotlin 很容易(authorities = roles.map { it.name }):

    fun AppUserEntity.toAppUserDetailsDTO() = AppUserDetailsDTO(
            id = id,
            username = appUserLogin,
            password = appUserPassword,
            authorities = roles.map { it.name },
            isEnabled               = isEnabled,
            isAccountNonLocked      = isAccountNonLocked,
            isAccountNonExpired     = isAccountNonExpired,
            isCredentialsNonExpired = isCredentialsNonExpired
    )

但是如何用 Java 和 Mapstruct 做到这一点?

【问题讨论】:

  • 虽然您显然不能在 Java 中使用扩展功能,但您可以通过一些实用方法来实现。 Java 的 Stream-API 允许将对象 A 映射到另一个对象 B……在我看来,这应该很容易。关于 MapStruct: 没用过,所以不能说太多。对不起。

标签: java spring-boot mapstruct


【解决方案1】:

在 Mapstruct 上,可以使用注解上的表达式属性对注解进行映射:expression = "java( yourJavaCodeHere )"

您的映射器将如下所示:

@Mapper(componentModel = "spring")
public abstract class AppUserDetailsDtoMapper {

    @Mappings({
            @Mapping(target = "username", source = "appUserLogin"),
            @Mapping(target = "password", source = "appUserPassword"),
            @Mapping(target = "authorities", expression = "java( mapAuthorities(user.getRoles()) )")
    })
    public abstract AppUserDetailsDTO toAppUserDetailsDTO(AppUserEntity user);

    protected Collection<GrantedAuthority> mapAuthorities(Set<RoleEntity> roles) {
        // Map the authorities here
    }
}

【讨论】:

  • 对不起,我忘了回答 - @Mapper(componentModel = "spring") 有什么原因吗?这个类是抽象的,不可能创建它的对象,所以我们不能自动装配它。
  • 要在映射器中使用 Spring IoC,我们需要将 componentModel 属性添加到 @Mapper ,其值为 spring。 Mapstruct 将创建该类的实现,因此您可以将其注入 @Autowired AppUserDetailsDtoMapper mapper
  • 为什么要使用表达式?将目标设为roles 就足够了。
  • rolesattributes 属于不同的类型,您可以为此定义另一个映射器,或者将它们映射到上面的抽象类中。
最近更新 更多