zoukankan      html  css  js  c++  java
  • 20211012 MapStruct

    环境信息

    • 最新版本:1.4.2.Final - 2021年4月19日
    • 笔记版本:1.4.2.Final

    MapStruct

    • MapStruct 是一个代码生成器,它基于约定优于配置的方法极大地简化了 Java bean 类型之间映射的实现
    • MapStruct 在编译时生成 Bean 映射(类似 Lombok)
    • MapStruct 是一个注释处理器(annotation processor )

    与 Lombok 共用

    需要确定好 lombok 和 mapstruct 的版本,部分版本不能一起使用

    参考官方文档

    <org.mapstruct.version>1.4.2.Final</org.mapstruct.version>
    <org.projectlombok.version>1.18.16</org.projectlombok.version>
    <lombok-mapstruct-binding.version>0.2.0</lombok-mapstruct-binding.version>
            
    
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>${org.mapstruct.version}</version>
    </dependency>
    
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct-processor</artifactId>
        <version>${org.mapstruct.version}</version>
    </dependency>
    
    <!-- lombok dependencies should not end up on classpath -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>${org.projectlombok.version}</version>
        <scope>provided</scope>
    </dependency>
    
    
    
    <build>
        <pluginManagement>
            <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>
                        <!-- See https://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html -->
                        <!-- Classpath elements to supply as annotation processor path. If specified, the compiler   -->
                        <!-- will detect annotation processors only in those classpath elements. If omitted, the     -->
                        <!-- default classpath is used to detect annotation processors. The detection itself depends -->
                        <!-- on the configuration of annotationProcessors.                                           -->
                        <!--                                                                                         -->
                        <!-- According to this documentation, the provided dependency processor is not considered!   -->
                        <annotationProcessorPaths>
                            <path>
                                <groupId>org.mapstruct</groupId>
                                <artifactId>mapstruct-processor</artifactId>
                                <version>${org.mapstruct.version}</version>
                            </path>
                            <path>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                                <version>${org.projectlombok.version}</version>
                            </path>
                            <path>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok-mapstruct-binding</artifactId>
                                <version>${lombok-mapstruct-binding.version}</version>
                            </path>
                        </annotationProcessorPaths>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
    

    代码示例

    简单使用

    // Source 类
    @Data
    @AllArgsConstructor
    public class Car {
    
        private String make;
        private int numberOfSeats;
        private CarType type;
    
    }
    
    // Target 类
    @Data
    public class CarDto {
    
        private String make;
        private int seatCount;
        private String type;
    
    }
    
    // Mapper 类
    @Mapper
    public interface CarMapper {
    
        CarMapper INSTANCE = Mappers.getMapper(CarMapper.class);
    
        @Mapping(source = "numberOfSeats", target = "seatCount")
        CarDto carToCarDto(Car car);
    }
    
    // 测试类
    public class CarMapperTest {
        @Test
        public void shouldMapCarToDto() {
            //given
            Car car = new Car("Morris", 5, CarType.SEDAN);
    
            //when
            CarDto carDto = CarMapper.INSTANCE.carToCarDto(car);
    
            //then
            System.out.println(carDto == null); // false
            System.out.println(carDto.getMake().equals("Morris"));  // true
            System.out.println(carDto.getSeatCount() == 5); // true
            System.out.println(carDto.getType().equals("SEDAN")); // true
        }
    }
    

    基本映射

    package study.mapstruct.demo2.dto;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import org.junit.Test;
    import org.mapstruct.*;
    import org.mapstruct.factory.Mappers;
    
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    
    
    
    public class PersonConverterTest {
        @NoArgsConstructor
        @AllArgsConstructor
        @Data
        static class Person {
            private Long id;
            private String name;
            private String email;
            private Date birthday;
            private User user;
        }
    
        @NoArgsConstructor
        @AllArgsConstructor
        @Data
        static class User {
            private Integer age;
        }
    
        @NoArgsConstructor
        @AllArgsConstructor
        @Data
        static class PersonDTO {
            private String id;
            private String name;
            /**
             * 对应 Person.user.age
             */
            private Integer age;
            private String email;
            /**
             * 与 DO 里面的字段名称(birthDay)不一致
             */
            private Date birth;
            /**
             * 对 DO 里面的字段(birthDay)进行拓展,dateFormat 的形式
             */
            private String birthDateFormat;
            /**
             * 对 DO 里面的字段(birthDay)进行拓展,expression 的形式
             */
            private String birthExpressionFormat;
    
        }
    
        @Mapper
        interface PersonConverter {
            PersonConverter INSTANCE = Mappers.getMapper(PersonConverter.class);
    
            @Mappings({
                    @Mapping(source = "birthday", target = "birth"),
                    @Mapping(source = "birthday", target = "birthDateFormat", dateFormat = "yyyy-MM-dd HH:mm:ss"),
                    @Mapping(target = "birthExpressionFormat", expression = "java(study.mapstruct.demo2.dto.PersonConverterTest.PersonConverter.format(person.getBirthday(),"yyyy-MM-dd HH:mm:ss"))"),
                    @Mapping(source = "user.age", target = "age"),
                    @Mapping(target = "email", ignore = false)
            })
            PersonDTO domain2dto(Person person);
    
            List<PersonDTO> domain2dtoList(List<Person> people);
    
            static String format(Date date, String format) {
                return new SimpleDateFormat(format).format(date);
            }
    
            /**
             * 自定义方法
             * @param value
             * @return
             */
            default Boolean convert2Bool(Integer value) {
                if (value == null || value < 1) {
                    return Boolean.FALSE;
                } else {
                    return Boolean.TRUE;
                }
            }
    
            /**
             * 继承配置
             * @param person
             * @param personDTO
             */
            @InheritConfiguration(name = "domain2dto")
            void update(Person person, @MappingTarget PersonDTO personDTO);
        }
    
        @Test
        public void test() {
            Person person = new Person(1L, "zhige", "zhige.me@gmail.com", new Date(), new User(1));
            System.out.println(person);
            PersonDTO personDTO = PersonConverter.INSTANCE.domain2dto(person);
            System.out.println(personDTO);
    
    
            List<Person> people = new ArrayList<>();
            people.add(person);
            List<PersonDTO> personDTOs = PersonConverter.INSTANCE.domain2dtoList(people);
            System.out.println(personDTOs);
    
    
            System.out.println(PersonConverter.INSTANCE.convert2Bool(1));
    
            PersonDTO personDTO2 = new PersonDTO();
            PersonConverter.INSTANCE.update(person, personDTO2);
            System.out.println(personDTO2);
        }
    }
    

    多对一

    package study.mapstruct.demo2.dto;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import org.junit.Test;
    import org.mapstruct.Mapper;
    import org.mapstruct.Mapping;
    import org.mapstruct.Mappings;
    import org.mapstruct.factory.Mappers;
    
    
    public class ItemConverterTest {
        @NoArgsConstructor
        @AllArgsConstructor
        @Data
        static class Item {
            private Long id;
            private String title;
        }
    
        @NoArgsConstructor
        @AllArgsConstructor
        @Data
        static class Sku {
            private Long id;
            private String code;
            private Integer price;
        }
    
        @NoArgsConstructor
        @AllArgsConstructor
        @Data
        static class SkuDTO {
            private Long skuId;
            private String skuCode;
            private Integer skuPrice;
            private Long itemId;
            private String itemName;
        }
    
        @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);
        }
    
        @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);
            System.out.println(skuDTO);
        }
    }
    

    Spring Boot 集成

    唯一需要改变的是注解

    @Mapper(componentModel="spring")
    

    生成的实现类上会带上注解 @Component

    参考资料

  • 相关阅读:
    ES6新特性:使用export和import实现模块化
    常见Linux/Unix开发辅助命令什锦
    Spark高速上手之交互式分析
    Lua中的元表与元方法
    explicit 构造函数
    【排序】基数排序(计数排序、桶排序)
    拓展训练—心得体会
    poj3411--Paid Roads(bfs+状压)
    点击单选button后的文字就可以选定相应单选button
    hdu 2349 最小生成树
  • 原文地址:https://www.cnblogs.com/huangwenjie/p/15396342.html
Copyright © 2011-2022 走看看