mapstruct-plus


一、基本介绍

mapstruct-plus 是对 MapStruct 的增强封装,提供如下特性:

  • 使用注解 @AutoMapper 自动生成单向或双向映射;
  • 自动注册到 Spring 容器;
  • 提供统一的 Converter 工具类;
  • 支持集合、嵌套对象、泛型映射;
  • 支持字段名不一致的映射;

二、快速集成

1. 添加依赖(Maven)

<dependency>
    <groupId>io.github.linpeilie</groupId>
    <artifactId>mapstruct-plus-spring-boot-starter</artifactId>
    <version>1.4.0</version> 
</dependency>

2. 启用注解处理器(IDEA)

  • 设置路径:
    File > Settings > Build, Execution, Deployment > Compiler > Annotation Processors
  • 勾选 ✅ “Enable annotation processing”

3.启用注解处理器

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>${lombok.version}</version>
                        </path>
                        <path>
                            <groupId>io.github.linpeilie</groupId>
                            <artifactId>mapstruct-plus-processor</artifactId>
                            <version>${mapstruct-plus.version}</version>
                        </path>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok-mapstruct-binding</artifactId>
                            <version>0.2.0</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>

三、基本用法

1. 定义 DTO 和 VO

@Data
public class UserDTO {
    private String username;
    private Integer age;
}
@Data
@AutoMapper(target = UserDTO.class)  // 自动生成双向映射
public class UserVO {
    private String username;
    private Integer age;
}

✅ 说明:此时会自动生成:

  • UserVO → UserDTO
  • UserDTO → UserVO

2. 使用 Converter 工具类

@Autowired
private Converter converter;

// VO → DTO
UserDTO dto = converter.convert(vo, UserDTO.class);

// DTO → VO
UserVO vo = converter.convert(dto, UserVO.class);

Converter 会在启动时收集所有 @AutoMapper 信息,并注册转换逻辑。


四、进阶用法

1. 关闭反向转换

@AutoMapper(target = UserDTO.class, reverseConvertGenerate = false)
public class UserVO { ... }

此时只能执行 VO → DTO,不能 DTO → VO。


2. 多目标映射

@AutoMappers({
        @AutoMapper(target = User2.class),
        @AutoMapper(target = User1.class),
})
public class UserVO { ... }

支持将 VO 同时映射到 DTO 和实体。


3. 自定义字段映射(字段名不同)

使用 @AutoMappings + @AutoMapping

@Data
@AutoMapper(target = UserDTO.class)
@AutoMappings({
    @AutoMapping(source = "name", target = "username"),
    @AutoMapping(source = "birth", target = "age", expression = "java(calculateAge(vo.getBirth()))")
})
public class UserVO {
    private String name;
    private LocalDate birth;
}

也可自定义 Mapper 接口。


4. 支持集合和分页对象

List<UserDTO> dtoList = converter.convert(voList, UserDTO.class);
Page<UserDTO> dtoPage = converter.convert(voPage, UserDTO.class);

支持 Spring Data、MyBatis Plus 等常见分页对象(自动封装)。


五、手动自定义 Mapper

@Mapper(componentModel = "spring")
public interface CustomMapper {

    UserDTO toDTO(UserVO vo);

    UserVO toVO(UserDTO dto);
}

然后注入使用:

@Autowired
private CustomMapper customMapper;

这种方式适合需要复杂逻辑或多个类组合映射时使用。


六、常见问题

1. 为什么 converter.convert(...) 报错说找不到转换器?

  • 原因:

    • 你的类没有加 @AutoMapper
    • 没开启 IDEA 的注解处理器
    • reverseConvertGenerate = false,却调用了反向转换
    • 没有正确引入 mapstruct-plus-spring-boot-starter
  • 解决方案:

    • 在 DTO、VO、Entity 中至少有一个类加上 @AutoMapper(target = Xxx.class)
    • 确保 IDEA 设置中 Enable annotation processing 打开
    • 检查 pom 中是否引入了 mapstruct-plus-spring-boot-starter
    • 检查生成的代码是否存在于 target/generated-sources/annotations 目录下
      • clean项目,rebuild project,再试

2. DTO ↔ Entity 字段名不一致,无法自动转换怎么办?

解决方案:

加上字段映射规则:

@AutoMappings({
    @AutoMapping(source = "name", target = "username")
})
@AutoMapper(target = UserDTO.class)
public class UserVO {
    private String name;
}

或使用 MapStruct 标准的 @Mapping 注解时自定义 Mapper 接口。


3. List<VO>Page<VO> 转换失败?

解决方案:

  • 确保单个对象的转换关系存在(VO ↔ DTO 已配置)

  • 使用 converter.convert(list, TargetClass.class),框架会识别集合类型

  • Page 仅支持常见分页实现,如:

    • org.springframework.data.domain.Page
    • com.baomidou.mybatisplus.extension.plugins.pagination.Page

4. 自动生成的 Mapper 类找不到?

解决方案:

  • 看看 target/generated-sources/annotations 目录是否存在生成的 XxxMapperImpl
  • IDEA 中没有索引这个目录时,Rebuild Project 一下
  • 检查是否设置了 module 编译输出路径

5. 支持多对一或一对多嵌套对象映射吗?

是的,支持嵌套对象、集合、泛型对象映射:

@AutoMapper(target = OrderDTO.class)
public class OrderVO {
    private List<OrderItemVO> items;
}

只要 OrderItemVO ↔ OrderItemDTO 的映射也存在,它会递归地完成嵌套映射。


6. 想要忽略某些字段怎么做?

使用 @AutoMapping(ignore = true) 或自定义 Mapper:

@AutoMappings({
    @AutoMapping(target = "password", ignore = true)
})
@AutoMapper(target = UserDTO.class)
public class UserVO {
    private String username;
    private String password; // 不希望传出去
}

7. 可以一个类映射多个目标类吗?

可以。一个类上可加多个 @AutoMapper 注解:

@AutoMapper(target = UserDTO.class)
@AutoMapper(target = UserEntity.class)
public class UserVO { ... }

注意:多个 target 时,生成的转换器名字会带有目标类名。


8. 兼容 Spring Boot 什么版本?

mapstruct-plus 没有强依赖 Spring Boot 版本,通常兼容:

  • Spring Boot 2.3 ~ 3.x
  • Spring Framework 5.x ~ 6.x

你可以在 spring.factories 中看到它通过自动配置方式启用。


9. 如何调试或查看生成的 Mapper 代码?

target/generated-sources/annotations/ 目录下,可以查看 XxxMapperImpl.java 文件,里面就是 MapStruct 实际生成的代码。


10. Lombok 和 MapStruct 冲突怎么办?

Lombok 与 MapStruct 并不冲突,但建议始终:

  • 开启注解处理器(两者都依赖)
  • 保证 Lombok、MapStruct、mapstruct-plus 的版本兼容
  • 避免在映射对象中使用 Lombok 的 @Builder(除非你知道它会影响构造器)

11.NoSuchConverterException: Cannot find converter from UserDTO to UserVO

两个类都没有标注 @AutoMapper,就等于你没有告诉框架要为这两个类生成映射关系,就会报这个

io.github.linpeilie.ConvertException: cannot find converter from TerminalModel to TerminalModelVo

字段名错误,字段名写成了user_name,但是使用mybatisplus查询结果是驼峰的,没法映射给user_name。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值