【问题标题】:How to use MapStruct for different data types?如何将 MapStruct 用于不同的数据类型?
【发布时间】:2019-11-26 18:00:42
【问题描述】:

我有两种类型的数据要映射:

SignUpUserDto:

public class SignUpUserDto {
    private String firstName;
    private String lastName;
    private String username;
    private String email;
    private String password;
    private String title;
}

注册用户:

@Entity
public class SignUpUser {
    private Long id;
    private String firstName;
    private String lastName;
    private String username;
    private String email;
    private String password;
    private Title title;
}

标题:

public enum Title {
    JUNIOR("junior"),
    MIDDLE("middle"),
    SENIOR("senior"),
    MANAGER("manager");

    private final String title;

    Title(final String title) {
        this.title = title;
    }

    public String toString() {
        return this.title;
    }
}
  • 对于 DTO,标题成员是 String

  • 对于entity,title 成员是一个Title

映射器应该是什么样子的?

我应该通过 Service 中已转换的标题吗?

@Mapper(componentModel = "spring")
public interface SignUpUserMapper {
    SignUpUserMapper INSTANCE = Mappers.getMapper(SignUpUserMapper.class);
    @Mapping(target = "title", expression = "title")
    public SignUpUserDto signUpUserToSignUpUserDto(SignUpUser signUpUser, String title);
    @Mapping(target = "title", source = "title")
    public SignUpUser signUpUserDtoToSignUpUser(SignUpUserDto signUpUserDto, Title title);
}

或者我应该在 Mapper 中进行转换吗?

@Mapper(componentModel = "spring",  imports = Title.class)
public interface SignUpUserMapper {
    SignUpUserMapper INSTANCE = Mappers.getMapper(SignUpUserMapper.class);
    @Mapping(target = "title", expression = "java(signUpUser.getTitle().toString())")
    public SignUpUserDto signUpUserToSignUpUserDto(SignUpUser signUpUser);
    @Mapping(target = "title", source = "java(new Title(signUpUserDto.getTitle()))")
    public SignUpUser signUpUserDtoToSignUpUser(SignUpUserDto signUpUserDto);
}

【问题讨论】:

  • 你不能这样做 new Title(...) 因为 Title 是 Enum 类

标签: java spring-boot mapstruct


【解决方案1】:

我应该传递已经在 Service 中转换的标题吗?

你绝对不应该这样做。这是转换器的工作,而不是服务的

尝试以下方法:

1) 给枚举类添加转换方法

enum Title {
    ...

    public static Title fromString(String title) {
        if (title != null) {
            for (Title t : Title.values()) {
                if (t.toString().equals(title)) {
                    return t;
                }
            }
        }
        return null;
    }
}

2) 向 Mapper 接口添加 2 种转换方法(仅限 Java 8+)

@Mapper(componentModel = "spring")
public interface SignUpUserMapper {
    SignUpUserDto signUpUserToSignUpUserDto(SignUpUser signUpUser);
    SignUpUser signUpUserDtoToSignUpUser(SignUpUserDto signUpUserDto);

    default String fromEnum(Title title) {
        return title == null ? null : title.toString();
    }

    default Title toEnum(String title) {
        return title == null ? null : Title.fromString(title);
    }
}

【讨论】:

  • 我在文档中看到了另一种使用抽象类而不是接口的选项。这两种方法有什么区别?你能给我一些用例吗?谢谢!
  • 当你需要将一些bean自动装配到mapper中时,你应该使用抽象类而不是接口
  • Java 8- 的方法是什么?为什么使用导入和@Mapping 注解不是一个好方法?我应该在具有自动装配功能的 Mappers 中包含存储库并在那里检索数据,还是应该在 Service 中执行此操作?
  • Java 8- 的方法相同,但由于 Java 8- 中没有默认接口方法,您将使用抽象类来代替
  • 一个补充:我认为转换为字符串是由 mapstruct 自动完成的,因此您不必为此添加方法。字符串的转换可以通过支持映射来完成,这可能更有效。
【解决方案2】:

像这样使用第二个选项:

 @Mapper(componentModel = "spring",  imports = Title.class)                     
public interface SignUpUserMapper {
SignUpUserMapper INSTANCE = Mappers.getMapper(SignUpUserMapper.class);
@Mapping(target = "title", expression = "java(signUpUser.getTitle().toString())")
public SignUpUserDto signUpUserToSignUpUserDto(SignUpUser signUpUser);
@Mapping(target = "title", source = "java(Title.valueOf(signUpUserDto.getTitle().toUpperCase()))")
public SignUpUser signUpUserDtoToSignUpUser(SignUpUserDto signUpUserDto);            
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    相关资源
    最近更新 更多