MapStruct,实现不同对象之间的转换

基本介绍

MapStruct工具类能实现不同对象之间的转换,类似于BeanUtils。

简单使用-不同对象之间的属性名相同

MapStruct工具类所需依赖:

<!--添加依赖-->
<dependency>
	 <groupId>org.mapstruct</groupId>
	 <artifactId>mapstruct</artifactId>
	 <version>1.5.1.Final</version>
</dependency>
<dependency>
	<groupId>org.mapstruct</groupId>
	<artifactId>mapstruct-processor</artifactId>
	<version>1.5.1.Final</version>
</dependency>
<dependency>
	<groupId>org.mapstruct</groupId>
	<artifactId>mapstruct-jdk8</artifactId>
	<version>1.5.1.Final</version>
</dependency>
<dependency>
	<groupId>org.projectlombok</groupId>
	<artifactId>lombok</artifactId>
	<version>1.18.26</version>
</dependency>

<build>
	<!--配合Lombok使用需要添加插件-->
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>1.5.1.Final</version>
                    </path>
                    <path>
                        <groupId>org.projectlombok</groupId>
                        <artifactId>lombok</artifactId>
                        <version>1.18.26</version>
                    </path>

                    <!-- additional annotation processor required as of Lombok 1.18.16 -->
                    <path>
                        <groupId>org.projectlombok</groupId>
                        <artifactId>lombok-mapstruct-binding</artifactId>
                        <version>0.2.0</version>
                    </path>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>
  1. 定义不同的实体
// Dog类和DogVo类的定义
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Dog {
    private String name;
}

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class DogVo {
    private String name;
}
  1. 自定义一个转换器接口,实现不同对象之间的转换
/**
 * 注意:@Mapper注解是mapstruct包下的
 * 如果希望将该Bean注入到Spring容器,可以将该注解的componentModel属性置为spring,可以实现自动注入
 */
@Mapper
public interface Dog2DogVoConvert {
    // 使用Mappers(mapstruct包下的一个工厂对象)根据接口的class对象获取一个转换器
    // 该对象是mapstruct自动帮我们实现接口的实现类对象
    Dog2DogVoConvert INSTANCE = Mappers.getMapper(Dog2DogVoConvert.class);

    // 定义一个方式,其功能为将一个对象转换为另一个对象
    DogVo dog2DogVo(Dog dog);
}
  1. 测试
public class SimpleTest {
    /**
     * 简单测试
     */
    @Test
    public void testSimpleDemoConvert() {
        // 定义一个Dog对象
        Dog dog = new Dog("Jack");
        // 使用mapstruct生成的实现类完成对象的转换
        DogVo dogVo = Dog2DogVoConvert.INSTANCE.dog2DogVo(dog);
        // 输出mapstruct生成的实现类的class类型,发现是接口的实现类,默认名称为:接口名Impl
        System.out.println(Dog2DogVoConvert.INSTANCE.getClass());
        // 输出转换后的数据,发现确实被转换了
        System.out.println("dogVo = " + dogVo);
    }
}

输出结果:

class com.lerqe.convert.Dog2DogVoConvertImpl
dogVo = DogVo(name=Jack)

进阶使用-不同对象之间的属性名不同

当要转换的对象中的某个属性和原来的对象属性名称不一致时,可以使用@Mapping注解实现属性的映射。
当要转换的对象中的多个属性和原来的的对象属性名称不一致时,可以使用Mappings+@Mapping注解来实现多个属性的映射

  1. 定义不同的实体
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class StorageSource {
    private Integer id;
    private String name;
    private List record;
}

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ResponseEntity {
    private Integer rid;
    private String rname;
    private List items;
}
  1. 自定义一个转换器接口,实现不同对象之间的转换
@Mapper
public interface StorageSource2ResponseEntityConvert {
    // 使用Mappers(mapstruct包下的一个工厂对象)根据接口的class对象获取一个转换器
    // 该对象是mapstruct自动帮我们实现接口的实现类对象
    StorageSource2ResponseEntityConvert INSTANCE = Mappers.getMapper(StorageSource2ResponseEntityConvert.class);

    // 定义一个方式,其功能为将一个对象转换为另一个对象
    // 使用@Mapping注解可以完成单个属性名不一致的转换,使用@Mappings+@Mapping注解可以实现多个属性名不一致的转换
    @Mappings({
            @Mapping(source = "id",target = "rid"),	// source代表原属性名,target代表要转换的属性名
            @Mapping(source = "name",target = "rname"),
            @Mapping(source = "record",target = "items")
    })

	// 定义一个方式,其功能为将一个对象转换为另一个对象
    ResponseEntity storageSource2ResponseEntity(StorageSource storageSource);

}
  1. 测试
    /**
     * 属性名不一致如何转换
     */
    @Test
    public void testFieldConvert() {
        List list = new ArrayList<>();
        Collections.addAll(list,"a","b","c");
        StorageSource jack = new StorageSource(1, "Jack", list);
        ResponseEntity responseEntity = StorageSource2ResponseEntityConvert.INSTANCE.storageSource2ResponseEntity(jack);
        System.out.println("responseEntity = " + responseEntity);
    }

输出结果:

responseEntity = ResponseEntity(rid=1, rname=Jack, items=[a, b, c])

进阶使用-集合的转换

当要转换的对象是一个集合且集合中泛型指定的对象属性名不一致时,我们数据额外添加一个方法,实现集合中泛型指定的对象的转换。

  1. 定义不同实体
// 集合中存储的对象
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Dog {
    private String name;
}

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Cat {
    private String catName;
}

// 要进行转换的对象
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class StorageSource {
    private Integer id;
    private String name;
    private List<Dog> record;	// 指定泛型
}

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ResponseEntity {
    private Integer rid;
    private String rname;
    private List<Cat> items;	// 指定泛型
}
  1. 自定义一个转换器接口,实现不同对象之间的转换
/**
 * 注意:@Mapper注解是mapstruct包下的
 * 如何希望将该Bean注入到Spring容器,可以将该注解的componentModel属性置为spring,可以实现自动注入
 */
@Mapper
public interface StorageSource2ResponseEntityConvert {
    // 使用Mappers(mapstruct包下的一个工厂对象)根据接口的class对象获取一个转换器
    // 该对象是mapstruct自动帮我们实现接口的实现类对象
    StorageSource2ResponseEntityConvert INSTANCE = Mappers.getMapper(StorageSource2ResponseEntityConvert.class);

    // 定义一个方式,其功能为将一个对象转换为另一个对象
    // 使用@Mapping注解可以完成单个属性名不一致的转换,使用@Mappings+@Mapping注解可以实现多个属性名不一致的转换
    @Mappings({
            @Mapping(source = "id",target = "rid"),
            @Mapping(source = "name",target = "rname"),
            @Mapping(source = "record",target = "items")
    })

    // 定义一个方式,其功能为将一个对象转换为另一个对象
    ResponseEntity storageSource2ResponseEntity(StorageSource storageSource);

    // 定义一个方式,其功能为将一个对象转换为另一个对象
    // 如何集合中存储的对象不一致时,使用该方法进行转换
    @Mapping(source = "name",target = "catName")
    Cat dog2Cat(Dog dog);
}
  1. 测试
@Test
    public void testFieldConvert() {
        List<Dog> list = new ArrayList<>();
        Collections.addAll(list,new Dog("a"),new Dog("b"),new Dog("c"));
        StorageSource jack = new StorageSource(1, "Jack", list);
        ResponseEntity responseEntity = StorageSource2ResponseEntityConvert.INSTANCE.storageSource2ResponseEntity(jack);
        System.out.println("responseEntity = " + responseEntity);
    }

输出结果:

responseEntity = ResponseEntity(rid=1, rname=Jack, items=[Cat(catName=a), Cat(catName=b), Cat(catName=c)])
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
当我们使用 MapStruct 进行 List 之间转换时,我们可以使用自定义的转换规则来实现,具体的步骤如下: 1. 定义自定义的转换方法 首先,我们需要在 Mapper 接口中定义一个自定义的转换方法,该方法接收两个参数,分别是源列表和目标列表,然后在方法体中实现转换逻辑。例如: ``` @Mapper public interface UserMapper { UserDto toDto(User user); User toEntity(UserDto dto); List<UserDto> toDtoList(List<User> userList); List<User> toEntityList(List<UserDto> dtoList); default List<UserDto> toDtoListWithCustomRule(List<User> userList) { return userList.stream().map(this::toDtoWithCustomRule).collect(Collectors.toList()); } default UserDto toDtoWithCustomRule(User user) { UserDto dto = toDto(user); // 自定义转换逻辑 dto.setFullName(user.getFirstName() + " " + user.getLastName()); return dto; } } ``` 在上面的例子中,我们定义了一个名为 toDtoWithCustomRule 的自定义方法,该方法接收一个 User 对象作为参数,返回一个经过自定义转换后的 UserDto 对象。在自定义方法中,我们可以实现任意的转换逻辑,比如在 UserDto 对象中设置一个全名属性,该属性值为 User 对象的 firstName 和 lastName 拼接而成。 2. 调用自定义的转换方法 接下来,我们可以在其他转换方法中调用自定义的转换方法,例如: ``` @Mapper public interface OrderMapper { OrderDto toDto(Order order); Order toEntity(OrderDto dto); List<OrderDto> toDtoList(List<Order> orderList); List<Order> toEntityList(List<OrderDto> dtoList); @Mapping(target = "userList", source = "order.userList") OrderDto toDtoWithCustomRule(Order order); @Mapping(target = "userList", source = "dto.userList") Order toEntityWithCustomRule(OrderDto dto); default List<OrderDto> toDtoListWithCustomRule(List<Order> orderList) { return orderList.stream().map(this::toDtoWithCustomRule).collect(Collectors.toList()); } default OrderDto toDtoWithCustomRule(Order order) { OrderDto dto = toDto(order); // 调用自定义转换方法 dto.setUserList(userMapper.toDtoListWithCustomRule(order.getUserList())); return dto; } default Order toEntityWithCustomRule(OrderDto dto) { Order order = toEntity(dto); // 调用自定义转换方法 order.setUserList(userMapper.toEntityListWithCustomRule(dto.getUserList())); return order; } } ``` 在上面的例子中,我们在 toDtoWithCustomRule 和 toEntityWithCustomRule 方法中调用了 UserMapper 中定义的 toDtoListWithCustomRule 和 toEntityListWithCustomRule 方法,实现了对 User 列表的转换。 3. 注册自定义的转换方法 最后,我们需要在 Mapper 接口上添加 @Component 注解,将该接口注册为 Spring 组件,以便让 MapStruct 自动将其实例化并使用其中定义的转换方法。 ``` @Mapper(componentModel = "spring", uses = UserMapper.class) @Component public interface OrderMapper { // 省略其他方法 } ``` 这样,我们就可以使用自定义的转换规则来实现 List 之间转换了。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值