Java 实体映射工具 MapStruct_zhuyu19911016520-CSDN博客

沙海
沙海
沙海
1017
文章
2
评论
2021年4月27日11:46:43
评论
2 5822字阅读19分24秒
摘要

Java 实体映射工具 MapStruct

Java 实体映射工具 MapStruct

Java 实体映射工具 MapStruct_zhuyu19911016520-CSDN博客

闪耀的瞬间
2020-09-11 16:21:38
Java 实体映射工具 MapStruct_zhuyu19911016520-CSDN博客
436

Java 实体映射工具 MapStruct_zhuyu19911016520-CSDN博客

收藏

1

分类专栏:
SpringBoot 项目开发
文章标签:
MapStruct

版权

Java 实体映射工具 MapStruct_zhuyu19911016520-CSDN博客

项目复杂性提升后,应用与应用之间,还有单独的应用细分模块之后,DO 一般不会让外部依赖,这时候需要在提供对外接口的模块里放 DTO 用于对象传输,也即是 DO 对象对内,DTO对象对外,DTO 可以根据业务需要变更,并不需要映射 DO 的全部属性。

这种 对象与对象之间的互相转换,就需要有一个专门用来解决转换问题的工具,毕竟每一个字段都 get/set 会很麻烦。

MapStruct 就是这样的一个属性映射工具,只需要定义一个 Mapper 接口,MapStruct 就会自动实现这个映射接口,避免了复杂繁琐的映射实现。MapStruct官网地址: http://mapstruct.org/ API教程下载:mapstruct-guide.pdf Java 实体映射工具 MapStruct_zhuyu19911016520-CSDN博客

工程中引入 maven 依赖

<properties>
    <mapstruct.version>1.4.1.Final</mapstruct.version>
</properties>

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

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>1.8</source> <!-- depending on your project -->
                <target>1.8</target> <!-- depending on your project -->
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>${mapstruct.version}</version>
                    </path>
                    <!-- other annotation processors -->
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>
12345678910111213141516171819202122232425262728293031323334353637383940414243
基本映射

有两个对象 User 和 UserDto需要转换,下面是这2个实体的属性

public class User implements Serializable {

    private String id;
    private String name;
    private String phoneNumber;
    private String email;
    private String photoUrl;
    private Boolean deleted;
    private Boolean used;
    
    //getter and setter ...
}

public class UserDto implements Serializable {
    private String name;
    private String phoneNumber;
    private String email;
    
    //getter and setter ...
}
1234567891011121314151617181920

添加UserModelConveter 接口,引入MapStruct相关功能

import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

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

    UserModelConverter INSTANCE = Mappers.getMapper(UserModelConverter.class);
    /**
     * 使用示例
     * 如果实体模型中的字段不一致,通过@Mapping注解手动对应
     @Mapping(source = "name", target = "fullName")
     PersonDto personToPersonDto(Person person);

     List<UserVO1> toConvertVOList(List<User> source);//转换集合
     */

    UserDto userToUserDto(User user);
}
123456789101112131415161718

若源对象属性与目标对象属性名字一致,会自动映射对应属性,不一样的需要手动指定

还可以用 format 转成自己想要的类型,如:转换格式的 birthDateFormat 加了dateFormat

如果某个属性你不想映射,可以加个 ignore=true

@Mapper(componentModel = "spring")
public interface UserModelConverter {
    UserModelConverter INSTANCE = Mappers.getMapper(UserModelConverter.class);
    @Mappings({
        @Mapping(source = "birthday", target = "birth"),
        @Mapping(source = "birthday", target = "birthDateFormat", dateFormat = "yyyy-MM-dd HH:mm:ss"),
        @Mapping(target = "birthExpressionFormat", expression = "java(org.apache.commons.lang3.time.DateFormatUtils.format(person.getBirthday(),\"yyyy-MM-dd HH:mm:ss\"))"),
        @Mapping(source = "user.age", target = "age"),
        @Mapping(target = "email", ignore = true)
    })
    PersonDTO domain2dto(Person person);

    List<PersonDTO> domain2dto(List<Person> people);
}
1234567891011121314

使用UserModelConverter转换model

User user = userService.getUserByPhoneNumber(phoneNumber);
UserDto userDto = UserModelConverter.INSTANCE.userToUserDto(user);
12

启动项目,编译之后, UserModelConverter 接口目录下会自动生成实现类,在 target/classes 下生成对应的实现类

Java 实体映射工具 MapStruct_zhuyu19911016520-CSDN博客

下面这个 UserModelConverterImpl 是自动生成的

package com.zypcy.userservice.mapstruct;

import com.zypcy.userservice.dto.UserDto;
import com.zypcy.userservice.entity.User;
import org.springframework.stereotype.Component;

@Component
public class UserModelConverterImpl implements UserModelConverter {
    public UserModelConverterImpl() {
    }

    public UserDto userToUserDto(User user) {
        if (user == null) {
            return null;
        } else {
            UserDto userDto = new UserDto();
            userDto.setId(user.getId());
            userDto.setName(user.getName());
            userDto.setPhoneNumber(user.getPhoneNumber());
            userDto.setEmail(user.getEmail());
            userDto.setPhotoUrl(user.getPhotoUrl());
            userDto.setUpdateDate(user.getUpdateDate());
            return userDto;
        }
    }
}
1234567891011121314151617181920212223242526
多对一

MapStruct 可以将几种类型的对象映射为另外一种类型,比如将多个 DO 对象转换为 DTO

例子:两个DO 对象 (Item 和 Sku),一个 DTO 对象 SkuDTO

@NoArgsConstructor
@AllArgsConstructor
@Data
public class Item {
    private Long id;
    private String title;
}

@NoArgsConstructor
@AllArgsConstructor
@Data
public class Sku {
    private Long id;
    private String code;
    private Integer price;
}

@NoArgsConstructor
@AllArgsConstructor
@Data
public class SkuDTO {
    private Long skuId;
    private String skuCode;
    private Integer skuPrice;
    private Long itemId;
    private String itemName;
}
123456789101112131415161718192021222324252627

创建 ItemConverter(映射)接口,MapStruct 就会自动实现该接口

@Mapper
public interface ItemConverter {
    ItemConverter INSTANCE = Mappers.getMapper(ItemConverter.class);

    @Mappings({
            @Mapping(source = "sku.id",target = "skuId"),
            @Mapping(source = "sku.code",target = "skuCode"),
            @Mapping(source = "sku.price",target = "skuPrice"),
            @Mapping(source = "item.id",target = "itemId"),
            @Mapping(source = "item.title",target = "itemName")
    })
    SkuDTO domain2dto(Item item, Sku sku);
}
12345678910111213

创建测试类,讲 Item 和 Sku 两个 DO对象,映射成一个 DTO 对象 SkuDTO

public class ItemConverterTest {
    @Test
    public void test() {
        Item item = new Item(1L, "iPhone X");
        Sku sku = new Sku(2L, "phone12345", 1000000);
        SkuDTO skuDTO = ItemConverter.INSTANCE.domain2dto(item, sku);
        assertNotNull(skuDTO);
        assertEquals(skuDTO.getSkuId(),sku.getId());
        assertEquals(skuDTO.getSkuCode(),sku.getCode());
        assertEquals(skuDTO.getSkuPrice(),sku.getPrice());
        assertEquals(skuDTO.getItemId(),item.getId());
        assertEquals(skuDTO.getItemName(),item.getTitle());
    }
}
1234567891011121314

MapStruct 注解关键词

@Mapper 只有在接口加上这个注解, MapStruct 才会去实现该接口
    @Mapper 里有个 componentModel 属性,主要是指定实现类的类型,一般用到两个
    default:默认,可以通过 Mappers.getMapper(Class) 方式获取实例对象
    spring:在接口的实现类上自动添加注解 @Component,可通过 @Autowired 方式注入
@Mapping:属性映射,若源对象属性与目标对象名字一致,会自动映射对应属性
    source:源属性
    target:目标属性
    dateFormat:String 到 Date 日期之间相互转换,通过 SimpleDateFormat,该值为 SimpleDateFormat              的日期格式
    ignore: 忽略这个字段
@Mappings:配置多个@Mapping
@MappingTarget 用于更新已有对象
@InheritConfiguration 用于继承配置
123456789101112

继续阅读
weinxin
资源分享QQ群
本站是一个IT技术分享社区, 会经常分享资源和教程; 分享的时代, 请别再沉默!
沙海
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: