美文网首页程序员干货分享
java对象映射工具--mapStruct

java对象映射工具--mapStruct

作者: 小白菜aaa | 来源:发表于2020-11-24 13:36 被阅读0次

    一般工程中会同时出现DTO和Entity两种类型的对象,Entity是数据库表直接对应的实体类,和数据库交互;DTO可以分为query,resp,save等不同功能,用于和前端做数据交互使用,可以根据具体业务需要增加任意属性,字段比较灵活。两种不同java类做转换的时候选用mapStruct相比直接set值要简洁得多。

    依赖导入

    <!-- https://mvnrepository.com/artifact/org.mapstruct/mapstruct -->
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>1.3.1.Final</version>
    </dependency>
    
    <dependencies>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${org.mapstruct.version}</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${org.mapstruct.version}</version>
                        </path>
                    </annotationProcessorPaths>
                    <compilerArgs>
                <compilerArg>
                    -Amapstruct.suppressGeneratorTimestamp=true
                </compilerArg>
                <compilerArg>
                    -Amapstruct.suppressGeneratorVersionInfoComment=true
                </compilerArg>
            </compilerArgs>
                </configuration>
            </plugin>
        </plugins>
    </build>
    
    

    常用注解

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

    Spring 注入的方式

    // 默认的方式
    PersonConverter INSTANCE = Mappers.getMapper(PersonConverter.class);
    
    @Mapper(componentModel="spring")
    
    

    基础用法

    一对一转换

    1.两个对象属性名相同,类型可能不同:可以直接写转换方法,不用写映射关系

    @Mapper
    public interface PersonConverter {
    //注入spring
        PersonConverter INSTANCE = Mappers.getMapper(PersonConverter.class);
    
    Dto entity2Dto(Entity entity)
    }
    
    

    2.两个对象字段名不同:只需要把属性名不同的字段进行映射,相同的部分不需要处理,如果有不想要映射的属性,可使用ignore

    @Mapper(componentModel="spring")
    public interface PersonConverter {
        //映射方法
        @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);
    }
    
    

    多对一转换

    转换是对应的属性,数据类型相同

    @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);
    }
    
    

    有时候, 我们不是想返回一个新的 Bean 对象, 而是希望更新传入对象的一些属性。这个在实际的时候也会经常使用到

    @Mapper
    public interface AddressMapper {
    
        AddressMapper INSTANCE = Mappers.getMapper(AddressMapper.class);
    
    /**
         * Person->DeliveryAddress, 缺失地址信息
         * @param person
         * @return
         */
        DeliveryAddress person2deliveryAddress(Person person);
    
        /**
         * 更新, 使用 Address 来补全 DeliveryAddress 信息。 注意注解 @MappingTarget
         * @param address
         * @param deliveryAddress
         */
        void updateDeliveryAddressFromAddress(Address address,
                                              @MappingTarget DeliveryAddress deliveryAddress);
    }
    
    

    一些好用的隐式类型转换:everything-String

    @Mapper(componentModel="spring")
    public interface CarMapper {
        //从int到String的转换
        @Mapping(source = "price", numberFormat = "$#.00")
        CarDto carToCarDto(Car car);
    
        @IterableMapping(numberFormat = "$#.00")
        List<String> prices(List<Integer> prices);
    }
    
    从BigDecimal到String的转换
    @Mapping(source = "power", numberFormat = "#.##E0")
        CarDto carToCarDto(Car car);
    
    从日期到字符串的转换
    @Mapping(source = "manufacturingDate", dateFormat = "dd.MM.yyyy")
        CarDto carToCarDto(Car car);
    
        @IterableMapping(dateFormat = "dd.MM.yyyy")
        List<String> stringListToDateList(List<Date> dates);
    
    

    嵌套bean映射

    @Mapper
    public interface FishTankMapper {
    
        @Mapping(target = "fish.kind", source = "fish.type")
        @Mapping(target = "fish.name", ignore = true)
        @Mapping(target = "ornament", source = "interior.ornament")
        @Mapping(target = "material.materialType", source = "material")
        @Mapping(target = "quality.report.organisation.name", source = "quality.report.organisationName")
        FishTankDto map( FishTank source );
    }
    
    

    默认值和常量的引入

    分别可以通过@Mapping的defaultValue和constant属性指定,当source对象的属性值为null时,如果有指定defaultValue将注入defaultValue的设定的值。constant属性通用用于给target属性注入常量值。

    @Mapper
    public interface SourceTargetMapper {
    
        SourceTargetMapper INSTANCE = Mappers.getMapper( SourceTargetMapper.class );
    
        @Mapping(target = "stringProperty", source = "stringProp", defaultValue = "undefined")
        @Mapping(target = "longProperty", source = "longProp", defaultValue = "-1")
        @Mapping(target = "stringConstant", constant = "Constant Value")
        @Mapping(target = "integerConstant", constant = "14")
        @Mapping(target = "longWrapperConstant", constant = "3001")
        @Mapping(target = "dateConstant", dateFormat = "dd-MM-yyyy", constant = "09-01-2014")
        @Mapping(target = "stringListConstants", constant = "jack-jill-tom")
        Target sourceToTarget(Source s);
    }
    
    

    外部转换方法的引入

    转换类

    @Mapper(componentModel="spring",uses = StringListMapper.class)
    public interface SourceTargetMapper {
        @Mappings({
                @Mapping(source = "modifyTime",target = "modifyTime",qualifiedByName = "LocalDateTime2String)        
        })
        SkuDto entity2Dto(Entity entity);
    }
    
    

    引入的外部方法类

    @Component
    @Named(”TypeCoversionMapping”)
    public class TypeCoversionMapping {
        @Named(“String2Double”)
        public Double StringentDouble (String value) {
            if(StringUtils.isBlank(value)|| value.equals(”“)){
                Return 0.0;
            }
            return new Double(value);
        }
    }
    

    结尾

    本文到这里就结束了,感谢大家看到最后,记得点赞加关注哦,如有不对之处还请多多指正。

    相关文章

      网友评论

        本文标题:java对象映射工具--mapStruct

        本文链接:https://www.haomeiwen.com/subject/zgucmktx.html