# mapstruct-demo **Repository Path**: note-java/mapstruct-demo ## Basic Information - **Project Name**: mapstruct-demo - **Description**: mapstruct笔记 - **Primary Language**: Java - **License**: MIT - **Default Branch**: dev - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2023-12-29 - **Last Updated**: 2025-06-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: MapStruct ## README # MapStruct ## 介绍 #### MapStruct 学习笔记 MapStruct 是一款强大的 Java 工具,专注于解决不同对象间的高效复制问题,如 PO(持久对象)、DTO(数据传输对象)、VO(视图对象)以及 QueryParam 之间的转换。相较于基于反射机制的 BeanUtils 类库,MapStruct 利用编译器生成针对性的方法,显著提升了转换性能。 #### JavaBean 转换问题背景 在实际开发中,我们常常面临众多 JavaBean 间的相互转换需求。过去,常见的处理方式包括: - ##### **拷贝技术** - 使用 Apache Commons 的 PropertyUtils.copyProperties 或 BeanUtils.copyProperties - Spring Framework 的 BeanUtils.copyProperties - CGLIB 的 BeanCopier 类进行快速拷贝 - ##### **手动 get/set** - 部分开发者借助 IDE 插件自动填充 set 方法实现对象复制,但这种方法可能并不为所有开发者熟知 - 即使如此,当新增字段时仍需手动更新,并且存在代码冗余和开发效率较低的问题 #### MapStruct 解决方案 MapStruct 是一款基于 Java 注解处理器的框架,它能够自动生成类型安全的 Bean 映射类。开发者只需定义一个映射器接口并声明所需的方法,编译阶段,MapStruct 就会创建对应的接口实现。这个实现利用简单的 Java get、set 方法执行源对象到目标对象的映射操作,而非依赖反射。 #### MapStruct 优势概述 1. **提高开发效率**:通过自动生成复杂的映射代码,避免了手写过程中可能出现的错误和繁琐劳动。 2. **编译时类型安全**:确保只有能互相匹配的对象及属性才能完成映射,有效防止诸如将订单实体误映射至客户 DTO 等错误发生。 3. **即时编译反馈**:当映射不完全(即未映射所有目标属性)或映射不正确(例如找不到适当的映射方法或类型转换时),编译器会在编译阶段就发出警告提示。 ## 使用 #### 引入maven依赖 ``` ... 1.5.5.Final 1.18.20 0.2.0 ... org.mapstruct mapstruct ${org.mapstruct.version} ... org.apache.maven.plugins maven-compiler-plugin 3.8.1 1.8 1.8 org.mapstruct mapstruct-processor ${org.mapstruct.version} org.projectlombok lombok ${lombok.version} org.projectlombok lombok-mapstruct-binding ${lombok-mapstruct-binding.version} ... ``` #### @Mapper配置项 | 选择 | 目的 | 违约 | | :----------------------------------------------- | :----------------------------------------------------------- | :-------- | | `mapstruct. suppressGeneratorTimestamp` | 如果设置为 ,则禁止在生成的映射器类的注释中创建时间戳。`true``@Generated` | `false` | | `mapstruct.verbose` | 如果设置为 ,则 MapStruct 在其中记录其主要决策。请注意,在 Maven 中编写时,由于 maven-compiler-plugin 配置中存在问题,也需要添加。`true``showWarnings` | `false` | | `mapstruct. suppressGeneratorVersionInfoComment` | 如果设置为 ,则禁止在生成的映射器类的注释中创建属性。注释包含有关 MapStruct 版本和用于注释处理的编译器的信息。`true``comment``@Generated` | `false` | | `mapstruct.defaultComponentModel` | 应基于哪个映射器生成映射器的组件模型的名称(请参阅[检索映射器](https://mapstruct.org/documentation/stable/reference/html/#retrieving-mapper))。支持的值为:`default`:映射器不使用组件模型,实例通常通过`Mappers#getMapper(Class)``cdi`:生成的映射器是应用程序范围的(来自 javax.enterprise.context 或 jakarta.enterprise.context,取决于哪个映射器在 javax.inject 具有优先级的情况下可用)CDI bean,可以通过`@Inject``spring`:生成的映射器是单例范围的 Spring bean,可以通过`@Autowired``jsr330`:生成的映射器用 {@code @Named} 注释,可以通过(从 javax.inject 或 jakarta.inject,取决于 javax.inject 具有优先级的可用映射器)进行检索,例如使用 Spring`@Inject``jakarta`:生成的映射器用 {@code @Named} 注解,可以通过(来自 jakarta.inject)检索,例如使用 Spring`@Inject``jakarta-cdi`:生成的映射器是应用程序范围的(来自 jakarta.enterprise.context)CDI bean,可以通过`@Inject`如果通过 为特定映射器提供组件模型,则注释中的值优先。`@Mapper#componentModel()` | `default` | | `mapstruct.defaultInjectionStrategy` | 映射器中通过参数 的注入类型。这仅用于基于注释的组件模型 例如 CDI、Spring 和 JSR 330。`uses`支持的值为:`field`:依赖项将被注入到字段中`constructor`:将生成构造函数。依赖项将通过构造函数注入。当 CDI 时,还将生成默认构造函数。 如果为特定映射器提供了注入策略 via ,则注解中的值优先于选项。`componentModel``@Mapper#injectionStrategy()` | `field` | | `mapstruct.unmappedTargetPolicy` | 在映射方法的目标对象的属性未填充源值时要应用的默认报告策略。支持的值为:`ERROR`:任何未映射的目标属性都会导致映射代码生成失败`WARN`:任何未映射的目标属性都会在生成时引起警告`IGNORE`:忽略未映射的目标属性如果通过 为特定映射器提供策略,则注释中的值优先。 如果通过 为特定的 Bean 映射提供策略,则它优先于 both 和 选项。`@Mapper#unmappedTargetPolicy()``@BeanMapping#unmappedTargetPolicy()``@Mapper#unmappedTargetPolicy()` | `WARN` | | `mapstruct.unmappedSourcePolicy` | 在映射方法的源对象的属性未填充目标值时应用的默认报告策略。支持的值为:`ERROR`:任何未映射的源属性都会导致映射代码生成失败`WARN`:任何未映射的源属性都会在生成时引起警告`IGNORE`:忽略未映射的源属性如果通过 为特定映射器提供策略,则注释中的值优先。 如果通过 为特定的 Bean 映射提供策略,则它优先于 both 和 选项。`@Mapper#unmappedSourcePolicy()``@BeanMapping#ignoreUnmappedSourceProperties()``@Mapper#unmappedSourcePolicy()` | `WARN` | | `mapstruct. disableBuilders` | 如果设置为 ,则 MapStruct 在执行映射时将不会使用构建器模式。这相当于为所有映射器执行此操作。`true``@Mapper( builder = @Builder( disableBuilder = true ) )` | `false` | #### @Mapping属性 ``` target:目标属性的名称,必须指定。 source:源属性的名称,如果与目标属性名称相同,则可以省略。 dateFormat:指定日期类型属性的格式化方式,例如:"yyyy-MM-dd"。 numberFormat:指定数字类型属性的格式化方式,例如:"#.00"。 constant:指定目标属性的常量值。 expression:使用表达式来计算目标属性的值。 defaultExpression:在源属性为 null 的情况下,使用表达式来计算目标属性的默认值。 ignore:是否忽略该映射。 qualifiedBy:指定一个或多个限定符以选择适当的映射方法。 qualifiedByName:指定一个或多个限定符名称以选择适当的映射方法。 conditionQualifiedBy:指定一个或多个条件限定符以选择适当的映射方法。 conditionQualifiedByName:指定一个或多个条件限定符名称以选择适当的映射方法。 conditionExpression:使用表达式来计算是否应该执行映射。 resultType:指定映射结果类型。 dependsOn:指定当前映射依赖的其他映射方法。 defaultValue:在源属性为 null 且无默认表达式的情况下,指定目标属性的默认值。 nullValueCheckStrategy:控制是否检查源对象和目标对象上的 null 值。 nullValuePropertyMappingStrategy:在源对象或目标对象上存在 null 值属性的情况下,控制如何处理目标对象上的 null 值属性。 mappingControl:指定映射控制实现类。 ``` 注意事项: - source与constant不能同时使用 - ***@BeanMapping(ignoreByDefault = true)***设置默认忽略未配置的属性 - numberFormat,使用DecimalFormat进行格式化,0:有就写没有就写0,#:有就写没有就不写,遵顼四舍五入原则 - expression需要写明具体包路劲,例***expression = "java(java.util.UUID.randomUUID().toString())"*** - qualifiedBy,与qualifiedByName类似可以绑定一个映射类,需要与@QName联用 - qualifiedByName需要与@QName联用 - conditionQualifiedBy与qualifiedBy类似,只适用于Condition方法 - conditionQualifiedByName同上 - ***@BeanMapping(resultType= Class)*** ## 定义映射器 #### 1.基本映射 ```JAVA import com.fjg.mapstructdemo.dto.UserInfoNew; import com.fjg.mapstructdemo.dto.UserInfoOld; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; import java.util.List; /** * 基础映射 * @author fengjianguo * @date 2023/12/29 13:42 */ @Mapper public interface UserInfoConvert { UserInfoConvert INSTANCE = Mappers.getMapper(UserInfoConvert.class); /** * 旧的实体类转换为新的实体类 * @param userInfoOld * @return */ @Mapping(source = "name",target = "userName") @Mapping(source = "sex",target = "userSex") @Mapping(source = "age",target = "userAge") @Mapping(source = "address",target = "userAddress") UserInfoNew convert(UserInfoOld userInfoOld); /** * 转换 * * @param userInfoOlds 用户信息旧版 * @return {@link List}<{@link UserInfoNew}> */ List convert(List userInfoOlds); } ``` ##### 说明: 1. @Mapper注解会导致MapStruct代码生成器在构建时创建CarMapper接口的实现。 2. 在生成的方法实现中,源类型(例如UserInfoOld)的所有可读属性将被复制到目标类型(例如UserInfoNew)的相应属性中。 3. 当属性与目标实体的属性同名时,它们将被隐式映射。 当属性在目标实体中具有不同的名称时,可以通过@Mapping注解指定其名称。 4. 必须在@Mapping注解中指定属性名称,该名称定义在JavaBeans规范中,例如对于具有访问器方法getName()和setName()的属性,名称为name。可以结合Lombok使用。 #### 2.映射合成 ```JAVA import org.mapstruct.Mapping; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 元注解 * ElementType.TYPE:类、接口、枚举等类型。 * ElementType.FIELD:字段(成员变量)。 * ElementType.METHOD:方法。 * ElementType.PARAMETER:方法参数。 * ElementType.CONSTRUCTOR:构造函数。 * ElementType.LOCAL_VARIABLE:局部变量。 * ElementType.ANNOTATION_TYPE:注解类型。 * ElementType.PACKAGE:包。 * ElementType.TYPE_PARAMETER:泛型类型参数。 * ElementType.TYPE_USE:类型使用。 * RetentionPolicy.CLASS,表示该注解将在编译期间保留 * RetentionPolicy.SOURCE:表示该注解只会在源代码中存在,在编译后会被丢弃,不能被读取到。 * RetentionPolicy.RUNTIME:表示该注解将在运行期间保留,并能够通过反射机制访问到。 * @author fengjianguo * @date 2023/12/29 14:08 */ @Retention(RetentionPolicy.CLASS) @Mapping(target = "id", expression = "java(java.util.UUID.randomUUID().toString())") @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) public @interface BaseEntity { } ``` ```JAVA import com.fjg.mapstructdemo.dto.UserInfoNew; import com.fjg.mapstructdemo.dto.UserInfoOld; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; import java.util.List; /** * 基础映射 * @author fengjianguo * @date 2023/12/29 13:42 */ @Mapper public interface UserInfoConvert { UserInfoConvert INSTANCE = Mappers.getMapper(UserInfoConvert.class); /** * 旧的实体类转换为新的实体类 * @param userInfoOld * @return */ @BaseEntity @Mapping(source = "name",target = "userName") @Mapping(source = "sex",target = "userSex") @Mapping(source = "age",target = "userAge") @Mapping(source = "address",target = "userAddress") UserInfoNew convert(UserInfoOld userInfoOld); /** * 转换 * * @param userInfoOlds 用户信息旧版 * @return {@link List}<{@link UserInfoNew}> */ List convert(List userInfoOlds); } ``` ##### 说明: 1. MapStruct 支持使用元注解,可以将通用的映射部分抽取出来 #### 3.向映射器添加自定义方法 ```JAVA /** * 旧的实体类转换为新的实体类 * * @param userInfoOld * @return */ @BaseEntity @Mapping(source = "name", target = "userName") @Mapping(source = "sex", target = "userSex") @Mapping(source = "age", target = "userAge") @Mapping(source = "address", target = "userAddress", qualifiedByName = "getAddress") UserInfoNew convert(UserInfoOld userInfoOld); /** * 自定义默认方法 * * @param address 地址 * @return {@link String } */ @Named("getAddress") default String getAddress(String address) { return address; } ``` ##### 说明: 1. 通过qualifiedByName与@Named进行绑定,在进行转换时找寻到该方法。 #### 4.多参数映射 ```JAVA /** * 旧的实体类转换为新的实体类 * * @param userInfoOld 用户信息旧 * @param userName 用户名 * @return {@link UserInfoNew } */ @Mapping(source = "userName", target = "userName") @Mapping(source = "userInfoOld.sex", target = "userSex") @Mapping(source = "userInfoOld.age", target = "userAge") @Mapping(source = "userInfoOld.address", target = "userAddress") UserInfoNew convert(UserInfoOld userInfoOld, String userName); ``` ##### 说明: 1. 如果多个源对象都使用相同的属性名称进行定义,必须使用@Mapping注解来指定从哪个源参数获取属性,就像示例中的userName属性一样。如果不解决这种歧义,将引发错误。对于在给定的源对象中只存在一次的属性,可以选择性地指定源参数的名称,因为它可以自动确定。 2. 在使用@Mapping注解时,指定属性所在的参数是强制的。 3. 具有多个源参数的映射方法在所有源参数都为null的情况下将返回null。否则,将实例化目标对象,并将提供的参数的所有属性传播到目标对象。 #### 5.嵌套bean映射 ```JAVA @Mapping(source="userInfoOld", target = ".") UserInfoOld toConvert(UserInfoNew userInfoNew); ``` ##### 说明: 1. 生成的代码将直接UserInfoNew.userInfoOld的每个属性映射到UserInfoOld,无需手动命名它们。 2. @Mapping(source="userInfoOld", target = ".")的意思是将 UserInfoNew对象的userInfoOld属性的所有属性映射到UserInfoOld对象本身的属性中,而不是将其映射到 UserInfoOld对象的一个名为 userInfoOld的属性上。 #### 6.更新现有的bean ```JAVA @Mapping(source = "userName", target = "userName") @Mapping(source = "userInfoOld.sex", target = "userSex") @Mapping(source = "userInfoOld.age", target = "userAge") @Mapping(source = "userInfoOld.address", target = "userAddress") void voidConvert(@MappingTarget UserInfoNew userInfoNew, UserInfoOld userInfoOld, String userName); ``` ##### 说明: 1. 在某些情况下,可能需要进行映射操作,而不是创建目标类型的新实例,而是更新现有的实例。这种类型的映射可以通过添加一个目标对象参数,并使用@MappingTarget注解标记该参数来实现。 #### 7.反向映射 ```JAVA /** * 旧的实体类转换为新的实体类 * * @param userInfoOld * @return */ @BaseEntity @Mapping(source = "name", target = "userName") @Mapping(source = "sex", target = "userSex") @Mapping(source = "age", target = "userAge") @Mapping(source = "address", target = "userAddress", qualifiedByName = "getAddress") UserInfoNew convert(UserInfoOld userInfoOld); /** * 新的实体类转换为旧的实体类 * * @param userInfoNew 用户信息新 * @return {@link UserInfoOld } */ @InheritInverseConfiguration UserInfoOld convert(UserInfoNew userInfoNew); ``` ##### 说明: 1. 为了减少重复编码,如果以及设置了正向映射(UserInfoOld => UserInfoNew)关系,可以直接通过@InheritInverseConfiguration进行反向映射(UserInfoNew => UserInfoOld )。 #### 8.map映射到bean ```JAVA @BeanMapping(ignoreByDefault = true) @Mapping(source = "name", target = "userName") @Mapping(source = "sex", target = "userSex") @Mapping(source = "age", target = "userAge") @Mapping(source = "address", target = "userAddress") UserInfoNew mapToBean(Map map); ``` ##### 注意: 1. 如果目标对象存在嵌套的bean必须对嵌套的bean设置映射关系,或者将嵌套的bean进行忽略。 ## 检索映射器(配置注入方式) #### 1.工厂注入 ```JAVA @Mapper public interface UserInfoConvert { UserInfoConvert INSTANCE = Mappers.getMapper(UserInfoConvert.class); UserInfoNew convert(UserInfoOld userInfoOld); } ``` ##### 说明: 1. 当不使用 DI 框架时,可以通过类检索 Mapper 实例。只需调用该方法,将映射器的接口类型传递给 return:`org.mapstruct.factory.Mappers``getMapper()` #### 2.指定注入策略 ```java @Mapper(componentModel = MappingConstants.ComponentModel.SPRING , uses = EngineMapper.class , injectionStrategy = InjectionStrategy.CONSTRUCTOR) public interface UserInfoConvert { UserInfoConvert INSTANCE = Mappers.getMapper(UserInfoConvert.class); /** * 旧的实体类转换为新的实体类 * * @param userInfoOld * @return */ @BaseEntity @Mapping(source = "name", target = "userName",qualifiedByName = "getEngineName") @Mapping(source = "sex", target = "userSex") @Mapping(source = "age", target = "userAge") @Mapping(source = "address", target = "userAddress", qualifiedByName = "getAddress") UserInfoNew convert(UserInfoOld userInfoOld); } @Mapper(componentModel = MappingConstants.ComponentModel.SPRING) public interface EngineMapper { /** * 获取引擎名称 * * @param engineName 发动机名称 * @return {@link String } */ @Named("getEngineName") default String getEngineName(String engineName) { return engineName + " engine"; } } ``` ##### 说明: 1. componentModel:指定了MapStruct生成的映射器实例应该被Spring管理。 2. uses:表示此映射器在进行映射时可能会用到`EngineMapper`类中的映射方法。有助于复用已定义的映射逻辑。 3. injectionStrategy:指定了MapStruct在注入依赖时应使用的策略为构造器注入。CONSTRUCTOR意味着MapStruct在生成映射器实现时,会优先通过构造器来注入依赖项,而不是使用字段注入或其他方式。 ## 数据类型转换 #### 1.基本类型转换 mapstruct会自动完成基本类型的一些隐式转换(包括:boolean、byte、char、int、long、float、double、String及其包装类等) 相同基本类型可以直接转换 StringBuilder与String可以直接转换 大数类型与基本类型及其包装类、String可以直接转换 ```JAVA @Mapping(target = "intValue", source = "intValue") @Mapping(target = "stringValue", source = "intValue") @Mapping(target = "stringValue", source = "booleanValue") // 强制转换,长字节类型转短字节类型会发生截断,注意数据溢出,精度丢失等问题。 @Mapping(target = "byteValue", source = "intValue") // 基本类型与其包装类型可以直接转换,且会自动生成判空代码 @Mapping(target = "intValue", source = "integerValue") ``` #### 2.时间类型转换 隐式转换规则 1. java.time.Instant与java.util.Date直接转换 2. java.sql.Date与java.util.Date直接转换 3. java.sql.Time 与java.util.Date直接转换 4. java.sql.Timestamp 与java.util.Date直接转换 ```JAVA @Mapper public interface TimeConvert { TimeConvert INSTANCE = Mappers.getMapper(TimeConvert.class); @Mapping(source = "localDateTime", target = "localDateTime", dateFormat = "yyyy-MM-dd HH:mm:ss") @Mapping(source = "date", target = "date", dateFormat = "yyyy-MM-dd HH:mm:ss") TimeNew convert(TimeOld timeOld); } @Data public class TimeNew { private String localDateTime; private String date; } @Data public class TimeOld { private LocalDateTime localDateTime; private Date date; } ``` #### 3.集合类型转换 ```JAVA @BaseEntity @Mapping(source = "name", target = "userName",qualifiedByName = "getEngineName") @Mapping(source = "sex", target = "userSex") @Mapping(source = "age", target = "userAge") @Mapping(source = "address", target = "userAddress", qualifiedByName = "getAddress") UserInfoNew convert(UserInfoOld userInfoOld); /** * 转换 * * @param userInfoOlds 用户信息旧版 * @return {@link List}<{@link UserInfoNew}> */ List convert(List userInfoOlds); ``` #### 4.枚举类型转换 ##### 4.1 枚举和枚举映射 ```JAVA // AgeEnum package com.fjg.mapstructdemo.enums; import lombok.AllArgsConstructor; import lombok.Getter; @Getter @AllArgsConstructor public enum AgeEnum { /** * 年龄 */ ZERO("0", "100"), ONE("1", "18"), TWO("2", "40"), THREE("3", "81"); private final String code; private final String desc; } // NameEnum package com.fjg.mapstructdemo.enums; import lombok.AllArgsConstructor; import lombok.Getter; @Getter @AllArgsConstructor public enum NameEnum { /** * 名字 */ ZERO("0", "未知"), ONE("1", "张三"), TWO("2", "李四"), THREE("3", "王五"); private final String code; private final String desc; } // 转换类 package com.fjg.mapstructdemo.convert; import com.fjg.mapstructdemo.enums.AgeEnum; import com.fjg.mapstructdemo.enums.NameEnum; import org.mapstruct.*; @Mapper(componentModel = MappingConstants.ComponentModel.SPRING) public interface NameEnumConvert { /** * 转换 * * @param ageEnum 年龄枚举 * @return {@link NameEnum } */ @ValueMappings({ @ValueMapping( source = MappingConstants.NULL, target = "ONE" ), @ValueMapping( source = "THREE", target = MappingConstants.NULL ), @ValueMapping( source = MappingConstants.ANY_REMAINING, target = "THREE" ) }) NameEnum convert(AgeEnum ageEnum); } ``` ###### 说明: ​ 1.@ValueMapping( source = MappingConstants.NULL, target = "ONE" ),表示如果ageEnum为null则返回AgeEnum.ONE ​ 2.@ValueMapping( source = "THREE", target = MappingConstants.NULL),表示如果传入AgeEnum.THREE,则返回null ​ 3.@ValueMapping( source = MappingConstants.ANY_REMAINING, target = "THREE" ),表示默认返回NameEnum.THREE ##### 4.2枚举和字符串映射 ```JAVA /** * 转换为str * * @param ageEnum 年龄枚举 * @return {@link String } */ @ValueMappings({ @ValueMapping( source = MappingConstants.NULL, target = "ONE" ), @ValueMapping( source = "THREE", target = "THREE" ), @ValueMapping( source = "ONE", target = "ONE" ), @ValueMapping( source = "TWO", target = "TWO" ), @ValueMapping( source = MappingConstants.ANY_UNMAPPED, target = "ZERO" ) }) String convertToStr(AgeEnum ageEnum); @InheritInverseConfiguration @ValueMapping(source = MappingConstants.ANY_REMAINING, target = "ZERO") AgeEnum convertToStr(String nameEnum); ``` ###### 说明: ​ 1.**MappingConstants.ANY_UNMAPPED**用于返回字符串,**MappingConstants.ANY_REMAINING**用于返回枚举 ##### 4.3自定义名称转换 ```JAVA // CustomEnum package com.fjg.mapstructdemo.enums; import lombok.AllArgsConstructor; import lombok.Getter; @Getter @AllArgsConstructor public enum CustomEnum implements BaseEnum { /** * 自定义枚举 */ ONE("1", "张三"), TWO("2", "李四"), THREE("3", "王五"); private final String code; private final String desc; } // CustomStateEnum package com.fjg.mapstructdemo.enums; import lombok.AllArgsConstructor; import lombok.Getter; @Getter @AllArgsConstructor public enum CustomStateEnum implements BaseEnum { /** * 自定义枚举 */ ONE_STATE("1", "张三"), TWO_STATE("2", "李四"), THREE_STATE("3", "王五"); private final String code; private final String desc; } // 转换类 package com.fjg.mapstructdemo.convert; import com.fjg.mapstructdemo.enums.CustomEnum; import com.fjg.mapstructdemo.enums.CustomStateEnum; import org.mapstruct.EnumMapping; import org.mapstruct.Mapper; import org.mapstruct.MappingConstants; @Mapper(componentModel = MappingConstants.ComponentModel.SPRING) public interface CustomEnumConvert { /** * 转换 * * @param customStateEnum 自定义状态枚举 * @return {@link CustomEnum } */ @EnumMapping(nameTransformationStrategy = MappingConstants.STRIP_SUFFIX_TRANSFORMATION, configuration = "_STATE") CustomEnum convert(CustomStateEnum customStateEnum); } ``` ###### 说明: ​ 1.@EnumMapping的策略 ​ a.MappingConstants.SUFFIX_TRANSFORMATION (添加源后缀) ​ b.MappingConstants.STRIP_SUFFIX_TRANSFORMATION (删除源后缀) ​ c.MappingConstants.PREFIX_TRANSFORMATION(添加源前缀) ​ d.MappingConstants.STRIP_PREFIX_TRANSFORMATION(删除源前缀)