本文主要是介绍Java中基于注解的代码生成工具MapStruct映射使用详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
《Java中基于注解的代码生成工具MapStruct映射使用详解》MapStruct作为一个基于注解的代码生成工具,为我们提供了一种更加优雅、高效的解决方案,本文主要为大家介绍了它的具体使用,感兴趣...
介绍
在 Java 开发中,我们经常需要在不同的 Java Bean 之间进行数据映射,比如从实体类(Entity)到数据传输对象(DTO)的转换。传统的做法是手动编写大量的 setter 和 getter 方法来完成属性的赋值,这种方式不仅繁琐,而且容易出错。MapStruct 作为一个基于注解的代码生成工具,为我们提供了一种更加优雅、高效的解决方案。它在编译时自动生成映射代码,避免了运行时反射带来的性能开销,同时保证了类型安全。
优缺点
优点
- 高性能:MapStruct 在编译阶段生成映射代码,运行时直接调用这些代码,避免了反射的使用,从而显著提高了性能。
- 类型安全:由于映射代码是在编译时生成的,编译器会对类型进行检查,因此可以在编译阶段发现类型不匹配等错误,避免了运行时异常。
- 代码简洁:使用 MapStruct 只需要定义映射接口和使用注解进行配置,无需手动编写大量的映射逻辑,大大减少了代码量,提高了开发效率。
缺点
- 学习成本:需要学习 MapStruct 提供的各种注解及其使用方法,对于初学者来说可能有一定的学习曲线。
- 依赖管理:需要在项目中引入 MapStruct 的相关依赖,增加了项目的依赖管理复杂度。
核心注解及详细使用语法说明
@Mapper
- 作用:用于标记一个接口为映射接口,MapStruct 会在编译时为该接口生成具体的实现类。
- 使用语法:
import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @Mapper public interface UserMapper { // 通过 Mappers.getMapper 方法获取映射接口的实例 UserMapper INSTANCE = Mappers.getMapper(UserMapper.class); // 定义从 UserEntity 到 UserDTO 的映射方法 UserDTO toDTO(UserEntity entity); // 定义从 UserDTO 到 UserEntity 的映射方法 UserEntity toEntity(UserDTO dto); }
@Mapping
- 作用:用于指定源对象和目标对象之间的属性映射关系,当源对象和目标对象的属性名
不一致
时,可以使用该注解进行显式映射
。 - 使用语法:
import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; @Mapper public interface UserMapper { UserMapper INSTANCE = Mappers.getMapper(UserMapper.class); // 使用 @Mapping 注解指定 entityId 映射到 id,entityName 映射到 name @Mapping(source = "entityId", target = "id") @Mapping(source = "entityName", target = "name") UserDTO toDTO(UserEntity entity); // 反向映射 @Mapping(source = "id", target = "entityId") @Mapping(source = "name", target = "entityName") UserEntity toEntity(UserDTO dto); }
@Mappings
- 作用:@Mappings 是 @Mapping 的集合形式,用于一次性指定
多个属性映射
关系。 - 使用语法:
import org.mapstruct.Mapper; import org.mapstruct.Mappings; import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; @Mapper public interface UserMapper { UserMapper INSTANCE = Mappers.getMapper(UserMapper.class); @Mappings({ @Mapping(source = "entityId", target = "id"), @Mapping(source = "entityName", target = "name") }) UserDTO toDTO(UserEntity entity); @Mappings({ @Mapping(source = "id", target = "entityId"), @Mapping(source = "name", target = "entityName") }) UserEntity toEntity(UserDTO dto); }
@Context
- 作用:用于在映射过程中传递上下文信息,比如一些辅助对象,这些对象可以在映射方法中使用。
- 使用语法:
import org.mapstruct.Mapper; import org.mapstruct.Context; import org.mapstruct.factory.Mappers; import java.util.Locale; @Mapper public interface UserMapper { UserMapper INSTANCE = Mappers.getMapper(UserMapper.class); // 使用 @Context 注解传递 Locale 对象作为上下文信息 UserDTO toDTO(UserEntity entity, @Context Locale locale); }
@AfterMapping
- 作用:用于在映射完成后执行自定义的逻辑,比如对目标对象的某些属性进行额外的处理。
- 使用语法:
import org.mapstruct.Mapper; import org.mapstruct.AfterMapping; import org.mapstruct.MappingTarget; import org.mapstruct.factory.Mappers; @Mapper public interface UserMapper { UserMapper INSTANCE = Mappers.getMapper(UserMapper.class); UserDTO toDTO(UserEntity entity); // 使用 @AfterMapping 注解定义映射完成后的自定义逻辑 @AfterMapping default void afterMapping(@MappingTarget UserDTO dto, UserEntity entity) { // 将源对象的 firstName 和 lastName 拼接后赋值给目标对象的 fullName 属性 dto.setFullName(entity.getFirstName() + " " + entity.getLastName()); } }
Demo示例
公共基本类定义
import lombok.Data; // 用户实体类 @Data public class UserEntity { private Long id; private String name; private Integer age; private String firstName; private String lastChina编程Name; private AddressEntity address; private Long entityId; private String entityName; } // 用户数据传输对象类 @Data public class UserDTO { private Long id; private String name; private Integer age; private String fullName; private AddressDTO address; private Long entityId; private String entityName; } // 地址实体类 @Data public class AddressEntity { private String street; private String city; } // 地址数据传输对象类 @Data public class AddressDTO { private String street; private String city; }
简单映射示例
import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @Mapper public interface UserMapper { // 获取映射接口的实例 UserMapper INSTANCE = Mappers.getMapper(UserMapper.class); // 从 UserEntity 到 UserDTO 的映射方法 UserDTO toDTO(UserEntity entity); jsUiD// 从 UserDTO 到 UserEntity 的映射方法 UserEntity toEntity(UserDTO dto); } // 测试代码 public class MainSimpleMapping { puwww.chinasem.cnblic static void main(String[] args) { UserEntity userEntity = new UserEntity(); userEntity.setId(1L); userEntity.setName("John"); userEntity.setAge(25); // 使用映射接口的实例进行映射 UserDTO userDTO = UserMapper.INSTANCE.toDTO(userEntity); System.out.println("简单映射示例结果:"); System.out.println("UserDTO: id=" + userDTO.getId() + ", name=" + userDTO.getName() + ", age=" + userDTO.getAge()); } }
输出结果:
简单映射示例结果:
UserDTO: id=1, name=John, age=25
字段名不一致的映射示例
import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; @Mapper public interface UserMapper { UserMapper INSTANCE = Mappers.getMapper(UserMapper.class); @Mapping(source = "entityId", target = "id") @Mapping(source = "entityName", target = "name") UserDTO toDTO(UserEntity entity); @Mapping(source = "id", target = "entityId") @Mapping(source = "name", target = "entityName") UserEntity toEntity(UserDTO dto); } // 测试代码 public class MainFieldNameMismatch { public static void main(String[] args) { UserEntity userEntity = new UserEntity(); userEntity.setEntityId(1L); userEntity.setEntityName("John"); userEntity.setAge(25); UserDTO userDTO = UserMapper.INSTANCE.toDTO(userEntity); System.out.println("字段名不一致映射示例结果:"); System.out.println("UserDTO: id=" + userDTO.getId() + ", name=" + userDTO.getName() + ", age=" + userDTO.getAge()); } }
输出结果:
字段名不一致映射示例结果:
UserDTO: id=1, name=John, age=25
嵌套对象映射示例
import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @Mapper public interface UserMapper { UserMapper INSTANCE = Mappers.getMapper(UserMapper.class); UserDTO toDTO(UserEntity entity); UserEntity toEntity(UserDTO dto); AddressDTO toDTO(AddressEntity entity); AddressEntity toEntity(AddressDTO dto); } // 测试代码 public class MainNestedObjectMapping { public static void main(String[] args) { AddressEntity addressEntity = new AddressEntity(); addressEntity.setStreet("123 Main St"); addressEntity.setCity("New York"); UserEntity userEntity = new UserEntity(); userEntity.setId(1L); userEntity.setName("John"); userEntity.setAddress(addressEntity); UserDTO userDTO = UserMapper.INSTANCE.toDTO(userEntity); SysjsUiDtem.out.println("嵌套对象映射示例结果:"); System.out.println("UserDTO: id=" + userDTO.getId() + ", name=" + userDTO.getName()); System.out.println("AddressDTO: street=" + userDTO.getAddress().getStreet() + ", city=" + userDTO.getAddress().getCity()); } }
输出结果:
嵌套对象映射示例结果:
UserDTO: id=1, name=John
AddressDTO: street=123 Main St, city=New York
自定义映射逻辑示例
import org.mapstruct.Mapper; import org.mapstruct.AfterMapping; import org.mapstruct.MappingTarget; import org.mapstruct.factory.Mappers; @Mapper public interface UserMapper { UserMapper INSTANCE = Mappers.getMapper(UserMapper.class); UserDTO toDTO(UserEntity entity); @AfterMapping default void afterMapping(@MappingTarget UserDTO dto, UserEntity entity) { dto.setFullName(entity.getFirstName() + " " + entity.getLastName()); } } // 测试代码 public class MainCustomMappingLogic { public static void main(String[] args) { UserEntity userEntity = new UserEntity(); userEntity.setId(1L); userEntity.setFirstName("John"); userEntity.setLastName("Doe"); UserDTO userDTO = UserMapper.INSTANCE.toDTO(userwww.chinasem.cnEntity); System.out.println("自定义映射逻辑示例结果:"); System.out.println("UserDTO: id=" + userDTO.getId() + ", fullName=" + userDTO.getFullName()); } }
输出结果:
自定义映射逻辑示例结果:
UserDTO: id=1, fullName=John Doe
使用上下文示例
import org.mapstruct.Mapper; import org.mapstruct.Context; import org.mapstruct.factory.Mappers; import java.util.Locale; @Mapper public interface UserMapper { UserMapper INSTANCE = Mappers.getMapper(UserMapper.class); UserDTO toDTO(UserEntity entity, @Context Locale locale); default String localize(String value, @Context Locale locale) { // 根据 locale 进行本地化处理 return value; } } // 测试代码 public class MainWithContext { public static void main(String[] args) { UserEntity userEntity = new UserEntity(); userEntity.setId(1L); userEntity.setName("John"); Locale locale = Locale.US; UserDTO userDTO = UserMapper.INSTANCE.toDTO(userEntity, locale); System.out.println("使用上下文示例结果:"); System.out.println("UserDTO: id=" + userDTO.getId() + ", name=" + userDTO.getName()); } }
输出结果:
使用上下文示例结果:
UserDTO: id=1, name=John
通过以上示例可以看到,使用 MapStruct 能够方便快捷地完成 Java Bean 之间的映射,同时结合 Lombok 的 @Data 注解进一步简化了代码。并且从输出结果可以直观地验证各个映射场景的正确性。
到此这篇关于Java中基于注解的代码生成工具MapStruct映射使用详解的文章就介绍到这了,更多相关Java MapStruct内容请搜索编程China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持China编程(www.chinasem.cn)!
这篇关于Java中基于注解的代码生成工具MapStruct映射使用详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!