【问题标题】:Use MapStruct to convert member variable to id (and vice versa)使用 MapStruct 将成员变量转换为 id(反之亦然)
【发布时间】:2021-04-26 00:15:12
【问题描述】:

在我的 SpringBoot 应用程序中,我有两个实体 UserRole

public class User {
    private Long id;
    private String email;
    private String password;
    private Set<Role> roles;

    [...]
}

public class Role {
    private Long id;
    private String name;
    private Set<User> users;

    [...]
}

我的 DTO 看起来非常相似,直到我意识到这可能会导致递归问题,当 user 的字段 role 具有相同的 user 字段时,该字段具有相同的 @987654327 字段@等

因此我决定只交给我的 DTO 的 ids,所以它们看起来像这样

public class UserDto {

    private Long id;
    private String email;
    private String password;
    private List<Long> roleIds;
}

public class RoleDto {
    private Long id;
    private String name;
    private List<Long> userIds;
}

我的映射器非常简单,过去看起来像这样

import org.mapstruct.Mapper;
@Mapper
public interface UserMapper {
    User userDtoToUser(UserDto userDto);
    UserDto userToUserDto(User user);
    List<UserDto> userListToUserDtoList(List<User> users);
}


import org.mapstruct.Mapper;
@Mapper
public interface RoleMapper {
    Role roleDtoToRole(RoleDto roleDto);
    RoleDto roleToRoleDto(Role Role);
    List<RoleDto> roleListToRoleDtoList(List<Role> roles);
}

我将如何更改它们以便它们将users 转换为/从userIdsroles 转换为/从roleIds

【问题讨论】:

    标签: java spring-boot type-conversion mapstruct


    【解决方案1】:

    rolesrolesDtosusersusersDtos 的单向映射非常简单

    @Mapper
    public interface RoleMapper {
    
        List<RoleDto> roleListToRoleDtoList(List<Role> role);
    
        @Mapping(target = "userIds", source = "users", qualifiedByName = "userListToUserDtoList")
        RoleDto roleToRoleDto(Role role);
    
        @Named("userListToUserDtoList")
        default List<Long> userListToUserDtoList(Set<User> users) {
            return users.stream().map(User::getId).collect(Collectors.toList());
        }
    }
    
    @Mapper
    public interface UserMapper {
    
        List<UserDto> userListToUserDtoList(List<User> users);
    
        @Mapping(target = "roleIds", source = "roles", qualifiedByName = "roleListToRoleDtoList")
        UserDto userToUserDto(User user);
    
        @Named("roleListToRoleDtoList")
        default List<Long> roleListToRoleDtoList(Set<Role> roles) {
            return roles.stream().map(Role::getId).collect(Collectors.toList());
        }
    }
    

    真正的问题是映射

    User userDtoToUser(UserDto userDto);
    

    Role roleDtoToRole(RoleDto roleDto);
    

    因为这里 MapStruct 不知道如何将 userIds 转换为 users 您需要一些机制来获取每个 userId 并将其解析为整个对象。如果您使用的是 Spring,您可以将映射器作为 Spring bean - https://mapstruct.org/documentation/stable/reference/html/#using-dependency-injection 或装饰器 https://mapstruct.org/documentation/stable/reference/html/#decorators-with-spring 用于“获取方法”以某种方式注入适当的存储库。
    ,但在这里我会考虑是否值得在定向映射中为您的recursion 案例进行挖掘或实施一些专用方法。

    【讨论】:

    • 谢谢@centrumek!我最终得到了一个类似的解决方案:映射器只创建用户/角色“骨架”,而不仅仅是 id 集。然后端点类有一个私有方法“丰富”,它遍历所有这些骨架并在持久性中搜索相应的对象。这可能不是很优雅,但它适用于我的目的......
    • @speendo 不客气。很高兴知道您已经找到了解决方案 :)
    猜你喜欢
    • 1970-01-01
    • 2021-07-05
    • 2010-12-03
    • 2011-10-08
    • 2013-03-15
    • 2019-09-19
    • 2013-12-29
    • 2011-09-22
    • 2012-05-14
    相关资源
    最近更新 更多