zoukankan      html  css  js  c++  java
  • MapStruct使用学习

    MapStruct通过一些接口定义,能自动生成实现类,将一个类转换为另一个类。

    引用

    <properties>
        <org.mapstruct.version>1.3.1.Final</org.mapstruct.version>
    </properties>
    ...
    <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>
                </configuration>
            </plugin>
        </plugins>
    </build>
    

    这个依赖有两个问题

    不支持lombok@Data等注解

    如果接口引用的类通过@Data标记,由于标记生成getter/setter等方法,但是在生成mapstruct mapper类时看不到,会导致编译找不到属性的问题。

    解决方法:引入mapstruct-processor,同时去掉plugin中的annotationProcessorPaths

    ...
        <dependency>
          <groupId>org.mapstruct</groupId>
          <artifactId>mapstruct-processor</artifactId>
          <version>1.3.1.Final</version>
          <scope>provided</scope>
        </dependency>
    ...
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
              <source>1.8</source>
              <target>1.8</target>
            </configuration>
          </plugin>
    ...
    

    Spring中无法通过@Autowired注入接口

    这是因为生成的Mapper实现类,没有被标注@Component,通过添加maven编译参数defaultComponentModel可以解决:

    ...
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
              <source>1.8</source>
              <target>1.8</target>
              <compilerArgs>
                <arg>-Amapstruct.defaultComponentModel=spring</arg>
              </compilerArgs>
            </configuration>
          </plugin>
    ...
    

    修改以后,我在eclipse中没有自动重新编译,需要clean再重新编译才生效。

    引用Mapper

    INSTANCE方式

    接口中定义一个单例,其他地方引用,官方讲的比较清楚:

    @Mapper
    public interface CarMapper {
    
        CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );
    
        CarDto carToCarDto(Car car);
    }
    
    //引用Mapper
    Car car = ...;
    CarDto dto = CarMapper.INSTANCE.carToCarDto( car );
    

    通过@Autowired依赖注入

    需要前面配置的defaultComponentModel=spring,才能在代码中注入:

    @Autowired
    CarMapper carMapper;
    

    其实上面的配置时全局的,也可以在mapper定义中,增加标记:

    @Mapper(componentModel = "spring")
    public interface CarMapper {
    
        CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );
    
        CarDto carToCarDto(Car car);
    }
    

    这样也行,只不过需要一个一个的Mapper都添加,不是那么方便了。

    使用

    可以转换复杂的结构类型,默认是同名的属性进行转换的。

    按照官方文档的说明,生成的Mapper代码也是尽量符合手写代码,通过getter/setter设置,没有使用反射,这也是为什么通过lombok添加getter/setter会生成不成功的原因。

    也支持通过注解,将不同名字的类型进行自动转换。

    我实验的代码:

    //源类型
    @Data
    public class TbUserCustomDO {
        private List<TbUser> users;
    
        private String fieldA;
    
        private String field2;
    }
    //TbUser也是一个自定义类
    @Data
    public class TbUser implements Serializable {
        private Integer id;
        private String username;
        private String password;
        private String name;
        private Integer age;
        private Integer sex;
        private Date birthday;
        private Date created;
        private Date updated
    }	
    
    //目的类
    @Data
    public class TbUserDemoDTO {
        private List<TbUserDTO> users;
    
        private String field1;
    
        private String field2;
    }
    //这里TbUserDTO与源类中的TbUser不完全相同(少一些字段),但是注意每个已有字段名称是相同的
    public class TbUserDTO {
        private Integer id;
        private String username;
        private String password;
        private String name;
        private Integer age;
        private Integer sex;
        private Date birthday;
    }	
    
    //Mapper类
    @Mapper
    public interface TbUserCustomConverter {
    
        //这里把fieldA对应到field1,因为名称不同
        @Mapping(source = "fieldA", target = "field1")
        TbUserDemoDTO doToDTO(TbUserCustomDO cDo);
    }
    
        //注入Mapper
        @Autowired
        TbUserCustomConverter tbUserCustomConverter;
        ...
        //使用,这里List和属性都能成功转换
        TbUserCustomDO cDo = ...
        TbUserDemoDTO dto = tbUserCustomConverter.doToDTO(cDo);
        
    
  • 相关阅读:
    在python中处理XML
    正则表达式
    python 反射
    python模块概况,json/pickle,time/datetime,logging
    python装饰器
    python3内置函数详解
    python函数,lambda表达式,三目运算,列表解析,递归
    python数据类型及其常用方法
    python3的文件操作
    初识Docker
  • 原文地址:https://www.cnblogs.com/mosakashaka/p/12609175.html
Copyright © 2011-2022 走看看