首页 > 其他分享 >使用mapstruct做对象属性转换

使用mapstruct做对象属性转换

时间:2023-10-11 17:33:40浏览次数:29  
标签:转换 映射 mapstruct 对象 Java User 注解 属性

MapStruct是一个Java注解处理器,它可以自动生成类型安全的Java Bean映射代码。MapStruct的主要目的是简化Java Bean之间的映射,它通过注解来指定Java Bean之间的映射规则,然后自动生成映射代码。

在MapStruct中,有几个常用的注解:

  1. @Mapper:用于指定一个Java Bean映射器接口,该接口定义了Java Bean之间的映射规则。

  2. @Mapping:用于指定Java Bean属性之间的映射关系。

  3. @Mappings:用于指定多个@Mapping注解,可以将多个Java Bean属性之间的映射关系组合在一起。

  4. @InheritInverseConfiguration:用于指定一个反向映射规则,可以将目标Java Bean映射回源Java Bean。

  5. @MappingTarget:用于指定一个目标Java Bean对象,可以将源Java Bean映射到目标Java Bean对象中。

  6. @AfterMapping:用于指定一个方法,在Java Bean映射完成后调用该方法。

下面是一个简单的MapStruct示例,其中定义了一个Java Bean映射器接口,用于将SourceBean映射到TargetBean中:

@Mapper
public interface BeanMapper {

    @Mapping(source = "sourceField", target = "targetField")
    TargetBean map(SourceBean sourceBean);

}

在上面的示例中,@Mapper注解用于指定BeanMapper接口是一个Java Bean映射器接口。@Mapping注解用于指定sourceField属性映射到targetField属性。然后,MapStruct会自动生成BeanMapper接口的实现代码,用于将SourceBean映射到TargetBean中。

需要注意的是,MapStruct中的注解非常灵活,可以根据实际需求进行组合和使用。同时,MapStruct还提供了丰富的配置选项,可以进一步定制生成的Java Bean映射代码。

 

MapStruct 的主要优点:

  • 生成类型安全的代码,减少了手写代码的错误和冗余;
  • 支持多种映射策略,包括注解、XML 配置、Java SPI 等;
  • 支持复杂类型的映射,如集合、嵌套对象等;
  • 支持自定义转换器,可以自定义转换逻辑;
  • 易于集成到现有项目中。

MapStruct 的使用步骤:

  1. 定义源类型和目标类型的 Java bean;
  2. 在源类型和目标类型中添加注解;
  3. 创建一个 Mapper 接口,并使用 @Mapper 注解标记它;
  4. 在 Mapper 接口中定义映射方法,使用 @Mapping 注解标记映射关系;
  5. 在需要进行映射的地方,使用 Mapper 接口的实现类进行映射。

示例:

假设有一个 User 类和一个 UserDto 类,需要将它们进行映射。

User 类:

public class User {
    private Long id;
    private String name;
    private Integer age;
    // getter/setter 略
}

UserDto 类:

public class UserDto {
    private Long id;
    private String username;
    private Integer age;
    // getter/setter 略
}

Mapper 接口:

@Mapper
public interface UserMapper {
    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
    
    @Mapping(source = "name", target = "username")
    UserDto userToUserDto(User user);
}

使用示例:

User user = new User();
user.setId(1L);
user.setName("Tom");
user.setAge(18);

UserDto userDto = UserMapper.INSTANCE.userToUserDto(user);

以上代码将会把 User 对象映射为 UserDto 对象,其中 User 的 name 属性会被映射到 UserDto 的 username 属性。

 

项目中使用示例:

1、引入依赖

<!--工具类:数据映射-->
<properties>
    <mapstruct.version>1.5.5.Final</mapstruct.version>
</properties>

<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>${mapstruct.version}</version>
</dependency>
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>${mapstruct.version}</version>
</dependency>

2、自定义转换接口

import org.mapstruct.Mapper;
import org.mapstruct.MappingConstants;

import java.util.List;

/**
 * @since 2023/8/17
 */
@Mapper(componentModel = MappingConstants.ComponentModel.SPRING)
public interface ObjectConverter {

    /**
     * request to dto list
     *
     * @param list
     * @return
     */
    List<TargetObjectDTO> toDtoList(List<SourceObjectDTO> list);
}

3、接口调用

public class CustomerController {

    private final ObjectConverter converter;

    public ApiResponse<Boolean> saveBatch(@RequestBody List<SourceObjectDTO> list) {

        boolean result = converter.toDtoList(list);
        return ApiResponse.ok(null);
    }
}

 

@MappingTarget 注解:

在 MapStruct 中,@MappingTarget 注解用于指定目标对象,以便在映射过程中将源对象的值映射到目标对象中。该注解可以用于方法级别或参数级别,用于指定要映射的目标对象。

@MappingTarget 注解的使用方法如下:

  1. 方法级别使用:
@Mapper
public interface UserMapper {

    @MappingTarget User map(UserDto userDto, @MappingTarget User user);

}

在上面的代码中,@MappingTarget 注解用于指定目标对象 User,将 UserDto 对象的值映射到 User 对象中。

  1. 参数级别使用:
@Mapper
public interface UserMapper {

    void map(UserDto userDto, @MappingTarget User user);

}

在上面的代码中,@MappingTarget 注解用于指定目标对象 User,将 UserDto 对象的值映射到 User 对象中。

需要注意的是,@MappingTarget 注解只能用于可变对象,即可以修改其属性值的对象。如果目标对象是不可变对象,如 Java 中的 String 类型,则不能使用 @MappingTarget 注解。

另外,@MappingTarget 注解还可以与其他注解一起使用,如 @Mapping、@InheritInverseConfiguration 等,以实现更复杂的映射逻辑。

 

@AfterMapping注解:

MapStruct是一个Java bean映射框架,它可以自动生成类型安全的映射代码,从而简化了Java bean之间的映射操作。在MapStruct中,@AfterMapping是一个注解,它可以用于在映射完成后执行一些自定义代码。

@AfterMapping注解可以用在方法上,用于在映射完成后执行一些额外的逻辑。该注解可以接受一个或多个参数,其中最重要的参数是source和target,它们分别表示源对象和目标对象。例如:

@Mapper
public interface UserMapper {

    @Mapping(target = "fullName", source = "firstName")
    @AfterMapping
    default void setFullName(@MappingTarget UserDTO userDTO, User user) {
        userDTO.setFullName(user.getFirstName() + " " + user.getLastName());
    }

    UserDTO userToUserDTO(User user);
}

在上面的例子中,我们定义了一个名为setFullName的方法,并使用@AfterMapping注解将其标记为映射完成后执行的方法。该方法接受两个参数,分别是UserDTO和User,它们分别表示映射后的目标对象和源对象。在该方法中,我们将源对象的firstName和lastName属性拼接成一个fullName属性,并设置到目标对象中。

需要注意的是,@AfterMapping注解只能用于void类型的方法,并且该方法的参数必须与映射方法的参数一致(除了@MappingTarget注解的参数)。此外,@AfterMapping注解还可以接受一个qualifiedBy参数,用于指定一个条件,只有当该条件成立时才执行该方法。例如:

@Mapper
public interface UserMapper {

    @Mapping(target = "fullName", source = "firstName")
    @AfterMapping(qualifiedBy = { FullNameCondition.class })
    default void setFullName(@MappingTarget UserDTO userDTO, User user) {
        userDTO.setFullName(user.getFirstName() + " " + user.getLastName());
    }

    UserDTO userToUserDTO(User user);
}

public class FullNameCondition {

    public boolean shouldSetFullName(UserDTO userDTO, User user) {
        return user.getLastName() != null;
    }
}

在上面的例子中,我们定义了一个名为shouldSetFullName的方法,并将其标记为FullNameCondition类的静态方法。该方法接受两个参数,分别是UserDTO和User,它们分别表示映射后的目标对象和源对象。在该方法中,我们判断源对象的lastName属性是否为null,如果不为null,则返回true,表示应该执行setFullName方法。在@AfterMapping注解中,我们使用qualifiedBy参数指定了FullNameCondition.class,表示只有当FullNameCondition.shouldSetFullName方法返回true时才执行setFullName方法。

 

@Mappings注解:

在MapStruct中,@Mappings注解用于指定多个@Mapping注解。它可以用于以下两种情况:

  1. 映射多个属性

当源对象和目标对象之间有多个属性需要映射时,可以使用@Mappings注解来指定多个@Mapping注解。

例如:

@Mapper
public interface CarMapper {

    @Mappings({
        @Mapping(source = "make", target = "manufacturer"),
        @Mapping(source = "numberOfSeats", target = "seatCount")
    })
    CarDto carToCarDto(Car car);
}

在上面的例子中,我们使用@Mappings注解来指定两个@Mapping注解,将源对象的“make”属性映射到目标对象的“manufacturer”属性,将“numberOfSeats”属性映射到“seatCount”属性。

  1. 忽略某些属性

有时候,我们希望在映射过程中忽略某些属性,可以使用@Mappings注解来指定忽略的属性。

例如:

@Mapper
public interface CarMapper {

    @Mappings({
        @Mapping(source = "make", target = "manufacturer"),
        @Mapping(source = "numberOfSeats", target = "seatCount"),
        @Mapping(target = "id", ignore = true)
    })
    CarDto carToCarDto(Car car);
}

在上面的例子中,我们使用@Mappings注解来指定三个@Mapping注解,将源对象的“make”属性映射到目标对象的“manufacturer”属性,将“numberOfSeats”属性映射到“seatCount”属性,并忽略目标对象的“id”属性。

总之,@Mappings注解是一个非常有用的注解,可以帮助我们在MapStruct中指定多个属性映射和忽略某些属性。

 

@InheritInverseConfiguration注解:

在使用 MapStruct 进行对象映射时,有时候我们需要将一个对象的属性值映射到另一个对象的属性上,同时也需要将这两个对象的属性映射反过来。这时候就可以使用 MapStruct 中的 @InheritInverseConfiguration 注解来实现反向映射。

@InheritInverseConfiguration 注解的作用是继承反向映射的配置,它通常与 @Mapping 注解一起使用。当我们在一个映射方法上使用了 @Mapping 注解指定了源对象属性和目标对象属性的映射关系时,MapStruct 会自动生成一个反向映射方法,用于将目标对象的属性值映射回源对象中。而 @InheritInverseConfiguration 注解就是用来继承这个自动生成的反向映射方法的配置。

下面是一个使用 @InheritInverseConfiguration 注解的示例:

java复制代码
@Mapper
public interface UserMapper {

    @Mapping(source = "name", target = "username")
    UserDTO toUserDTO(User user);

    @InheritInverseConfiguration
    User toUser(UserDTO userDTO);
}

在上面的示例中,我们定义了一个 UserMapper 接口,其中包含两个方法:toUserDTO()toUser()toUserDTO() 方法用于将 User 对象映射为 UserDTO 对象,其中指定了 name 属性映射到 username 属性上。而 toUser() 方法则用于将 UserDTO 对象映射为 User 对象,并使用 @InheritInverseConfiguration 注解继承了自动生成的反向映射方法的配置。

 

标签:转换,映射,mapstruct,对象,Java,User,注解,属性
From: https://www.cnblogs.com/huangdh/p/17757747.html

相关文章

  • .net 关于在program中使用AddNewtonsoftJson之后,继承于System.Text.Json.Serializatio
    首先,先说遇见的问题与代码示例,在.net代码中注册了如下代码.AddNewtonsoftJson(option=>{//使用本地时区option.SerializerSettings.DateTimeZoneHandling=DateTimeZoneHandling.Local;......
  • MetaObjectHandler:实体对象的属性自动赋值
    1.MetaObjectHandler接口方法Mybatis中的MetaObjectHandler是一个接口,用于为实体对象的属性自动赋值。它有以下几个方法:insertFill(MetaObjectmetaObject):在执行插入操作时自动填充实体对象的属性值。updateFill(MetaObjectmetaObject):在执行更新操作时自动填充实体对象......
  • 日期格式转换异常:Java 8 date/time type `java.time.LocalDateTime` not supported by
    异常信息:"unexpectederror:Typedefinitionerror:[simpletype,classjava.time.LocalDateTime];nestedexceptioniscom.fasterxml.jackson.databind.exc.InvalidDefinitionException:Java8date/timetype`java.time.LocalDateTime`notsupportedbydefault:......
  • 无涯教程-ASP.NET Core - 属性路由
    在本章中,无涯教程将学习另一种路由方法,即基于属性的路由,通过基于属性的路由,可以在控制器类和这些类内部的方法上使用C#属性,这些属性具有告诉ASP.NETCore何时调用特定控制器的元数据。它是基于约定的路由的替代方法。按照出现的顺序,注册的顺序对路由进行判断,但是映射多个路由是......
  • Flex布局的三个属性要深刻理解!
    在我们日常开发中,flex布局可以说是家常便饭,对于很多的我们来说(你懂得^_^),可能我们用的比较多的应该就是垂直居中里,也就是下面这段代码:.flex-box{display:flex;justify-content:center;align-items:center;}写的非常好(^_^)!然后我们都知道这个是定义在父元素的,布局效果是......
  • Asp.net core中HttpResponse常用属性及Status code
    在ASP.NETCore中,HttpResponse表示HTTP响应,其中包括一些常用的属性和方法,用于设置HTTP响应的各种属性。HTTP响应通常由一个HTTP状态码,HTTP头(headers),和HTTP主体(body)组成。以下是一些常用的HttpResponse属性和一些常见的HTTP状态码及其含义:HttpResponse常用属性:StatusCode:用......
  • 图扑 HT for Web 风格属性手册教程
    图扑软件明星产品HTforWeb是一套纯国产化独立自主研发的2D和3D图形界面可视化引擎。HTforWeb(以下简称HT)图元的样式由其Style属性控制,并且不同类型图元的Style属性各不相同。为了方便查询和理解图元的Style属性,以及更加便捷地应用和理解每个属性的作用,图扑HT提......
  • 解决前端传递Date类型时自动转换为国际时间的问题
    本质原因是前端对象中使用了Data类型的属性字段,在向后端传递时会自动将JSON对象转换为JSON字符串进行传递Date类型的属性在进行转换时会调用自身的toJSON方法,转换为国际时间的字符串表达形式letdate=newDate();console.log(date);console.log(JSON.stringify(date));导......
  • 表单元素的enctype属性
    表单元素的enctype属性指定的是表单数据的编码方式,该属性有3个值:1)application/x-www-form-urlencoded:这是默认编码方式,它只处理表单域里的value属性值,采用这种编码方式的表单会将表单域的值处理成URL编码方式。2)multipart/form-data:这种编码方式的表......
  • oss存储类型转换及解冻(下)
    oss存储类型转换及解冻(下)这篇就干货满满了,搞了我一天多,差点把我老命送走,也差点把阿里客服搞吐血,各种问题各种问(为了快速出结果),给领导交待  上篇提到,归档后的文件是无法访问的(除去归档直读),也说到我把一个月的测试文件分了三批,对应三种类型。一、筛选不同类型的文件......