美文网首页
Mapstruct-使用

Mapstruct-使用

作者: wang_cheng | 来源:发表于2020-06-06 16:11 被阅读0次

    看下使用

    @Mapper(componentModel = "spring")
    public interface ReturnAddressModelTransformMapper {
    
        @Mapping(source = "addressId",target = "id")
        TSellerReturnAddress returnAddressVO2DBO(SellerReturnAddressVO sellerReturnAddressVO);
    

    之前遇到javaBean之间的转换,可能一般都用BeanUtil.copyProperties直接转换了,但是这种底层还是用的反射来实现的,多少有点损耗性能,虽然各大框架已经对反射信息进行缓存提高性能了.但是遇到类型不一致的可能还要手动去set一下,或者有的值并不想返回....

    当然还有类似的这种javabean转换框架,以下是对几种对象映射框架的对比,大多数情况下 MapStruct 性能最高。原理类似于lombok ,MapStruct都是在编译期进行实现,而且基于Getter、Setter,没有使用反射所以一般不存在运行时性能问题。

    image.png

    开始正题:直接使用入门

    需要的pom文件

    <properties>
            <org.mapstruct.version>1.2.0.CR1</org.mapstruct.version>
        </properties>
    <!--mapstruct-->
            <dependency>
                <groupId>org.mapstruct</groupId>
                <artifactId>mapstruct-jdk8</artifactId>
                <version>${org.mapstruct.version}</version>
            </dependency>
            <dependency>
                <groupId>org.mapstruct</groupId>
                <artifactId>mapstruct-processor</artifactId>
                <version>${org.mapstruct.version}</version>
                <scope>provided</scope>
            </dependency>
    

    这边准备两个对象

    数据库实体类 DBO

    @Table(name = "t_seller_return_address")
    @Getter
    @Setter
    @ToString
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    public class DBO {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
    
        /**
         * 收件人姓名
         */
        @Column(name = "receive_name")
        private String receiveName;
    
    
        /**
         * 创建时间
         */
        @Column(name = "create_time")
        private Date createTime;
    
        private String password;
    
    
    }
    

    VO层 VO

    @Data
    public class VO {
      
        private Integer addressId;
    
        private String name;
    
        private String password;
    
        private String startTime;
    
    }
    

    返回出去的时候,希望DBO和VO对应关系是
    id---->addressId
    receiveName--->name
    createTime----->startTime(Date类型->String类型(yyyy-MM-dd HH:mm:ss))

    先创建一个转换Mapper

    包别引错了噢,不是Mybatis的
    import org.mapstruct.Mapper;

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

    还有一种方式集成spring,引入的时候可以直接@Autowired进去

    @Mapper(componentModel = "spring")
    public interface ModelTransformMapper {
         
    }
    

    写一个方法进行转换

    @Mapper
    public interface ModelTransformMapper {
    
        @Mappings({
                @Mapping(source = "id",target = "addressId"),
                @Mapping(source = "receiveName",target = "name"),
                @Mapping(source = "createTime",target = "startTime",dateFormat = "yyyy-MM-dd HH:mm:ss")
                @Mapping(source="password",ignore=true)
        })
        VO dbo2vo(DBO dbo);
    }
    }
    

    @Mappings注解内值

    public @interface Mapping {
        String target();
    
        String source() default "";
    
        String dateFormat() default "";
    
        String numberFormat() default "";
    
        String constant() default "";
    
        String expression() default "";
    
        boolean ignore() default false;
    
        Class<? extends Annotation>[] qualifiedBy() default {};
    
        String[] qualifiedByName() default {};
    
        Class<?> resultType() default void.class;
    
        String[] dependsOn() default {};
    
        String defaultValue() default "";
    }
    

    source:源字段,需要被转换的字段
    target:目标字段,需要转成的字段
    dateFormat:日期格式化
    ignore:密码不应该返回给前台,可以设置为忽略为true
    defaultValue:可以给予默认值,防止为Null出现不可预期的错误
    constant:给目标值设定常量值,注意使用这个,就不要指定 source 源了,因为目标对象是常量

    调用转换

    • spring注入方式
    @Autowired
    private ModelTransformMapper modelTransformMapper;
    
       //直接调用
        VO = modelTransformMapper.dbo2vo(dbo);
    
    • 使用默认工厂模式
    VO = ModelTransformMapper.INSTANCE.dbo2vo(dbo);
    

    多参数

    两个对象组装一个公共对象返回

    @Mapper
    public interface AddressMapper {
    
        @Mappings({
            @Mapping(source = "person.description", target = "description"),
            @Mapping(source = "address.houseNo", target = "houseNumber")
        })
        DeliveryAddressDto personAndAddressToDeliveryAddressDto(Person person, Address address);
    }
    1. 当多个对象中, 有其中一个为 null, 则会直接返回 null
    2. 如一对一转换一样, 属性通过名字来自动匹配。 因此, 名称和类型相同的不需要进行特殊处理
    3. 当多个原对象中,有相同名字的属性时,需要通过 @Mapping 注解来具体的指定, 以免出现歧义(不指定会报错)。 
    如上面的 description 属性也可以直接从传入的参数来赋值。
    
    

    更新 Bean 对象 @MappingTarget

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

    @Mapper
    public interface CarMapper {
        // 使用CarDto来更新Car对象,相同名称属性直接更新值
        void updateCarFromDto(CarDto carDto, @MappingTarget Car car);
    }
    

    不同类型转换处理

    比如常见的数据库里查的是Boolean类型的,但是返回出去可能是String类型的 "是","否",这时需要特殊处理下

    • 自定义转换规则
    @Mapper
    public interface CarMapper {
       
        default VO transform(DBO dbo){
    
          //todo 自定义规则
            SellerBasicInfoDTO basicInfo = new SellerBasicInfoDTO();
            basicInfo.setFreeSeven(userInfo.getFreeSevenReturn() ? 1 : 0);
            basicInfo.setInvoice(userInfo.getSupportInvoice() ? 1 : 0);
            return basicInfo;
      }
    }
    
    • 通过引用已有的通用类

    如果你的Mapper类配置的是Spring的,记住@Component这个注解一定记得要加,不然spring扫描不到

    @Component
    public class BaseCommonTransform {
    
        Integer boolean2Integer(Boolean value){
            if (value == null){
                return 0;
            }
            return value ? 1 :0;
        }
    
    }
    
    @Mapper(componentModel = "spring",uses = BaseCommonTransform.class)
    public interface LargeSellerCommonMapper {
    
        @Mappings({
                @Mapping(source = "freeSevenReturn",target = "freeSeven"),
                @Mapping(source = "supportInvoice",target = "invoice")
        })
        SellerBasicInfoDTO userInfoDBO2DTO(TSellerUserInfo userInfo);
    }
    

    相关文章

      网友评论

          本文标题:Mapstruct-使用

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