springboot MapStruct使用入门教程笔记

springboot MapStruct使用入门教程笔记

MapStruct可以减少编码量,dto,entity相互转换时,自动生成set,get方法的调用。

2022-08-11 Goldchenn

掌握的技术,够用就行,坐个公交车,难道要把公交车的所有研发技术都掌握吗?

一、maven依赖


<properties>
 <mapstruct.version>1.5.2.Finalmapstruct.version>
properties>

<dependency>
    <groupId>org.mapstructgroupId>
    <artifactId>mapstructartifactId>
    <version>${mapstruct.version}version>
dependency>
<dependency>
    <groupId>org.mapstructgroupId>
    <artifactId>mapstruct-processorartifactId>
    <version>${mapstruct.version}version>
    <scope>providedscope> 
dependency>
<dependency>
    <groupId>javax.injectgroupId>
    <artifactId>javax.injectartifactId>
    <version>1version>
dependency>

建议安装插件 mapstruct support,按 ctrl + 鼠标左键 ,会跳转到参数对应的类

二、准备实体类

package space.goldchen.mapstruct.domain;

import lombok.Data;

/**
 * @author goldchen
 * @create 2022-08-12 8:50
 */
@Data
public class Pig {
    private Long id;
    private String name;
    private Integer age;
}

package space.goldchen.mapstruct.domain;

import lombok.Data;

/**
 * @author goldchen
 * @create 2022-08-12 9:08
 */
@Data
public class Person {
    private Long id;
    private String name;
}

三、准备DTO

package space.goldchen.mapstruct.service.dto;

import lombok.Data;

/**
 * @author goldchen
 * @create 2022-08-12 8:53
 */
@Data
public class PigDto {
    private Long id;
    private String name;
    private Integer age;
}
package space.goldchen.mapstruct.service.dto;

import lombok.Data;

/**
 * @author goldchen
 * @create 2022-08-12 9:09
 */
@Data
public class PigInfoDto {
    private Long id;
    private String name;
    private Integer age;
    private String personName;
}

四、默认方式使用

1. 创建Mapper

package space.goldchen.mapstruct.service.mapstruct;

import space.goldchen.mapstruct.domain.Pig;
import space.goldchen.mapstruct.service.dto.PigDto;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;

/**
 * @author goldchen
 * @create 2022-08-12 9:07
 */
@Mapper
public interface PigMapper {
    public static PigMapper MAPPER = Mappers.getMapper(PigMapper.class);
    //  属性名称一致时,可以省略
    @Mappings({
            @Mapping(source = "id",target = "id"),
            @Mapping(source = "name",target = "name"),
            @Mapping(source = "age",target = "age")
    })
    public PigDto from(Pig pig);
}
package space.goldchen.mapstruct.service.mapstruct;

import space.goldchen.mapstruct.domain.Person;
import space.goldchen.mapstruct.domain.Pig;
import space.goldchen.mapstruct.service.dto.PigInfoDto;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;

/**
 * @author goldchen
 * @create 2022-08-12 9:54
 */
@Mapper
public interface PigInfoMapper {
    PigInfoMapper MAPPER = Mappers.getMapper(PigInfoMapper.class);
    //  属性名称一致时,可以省略
    @Mappings({
            @Mapping(source = "pig.id",target = "id"),
            @Mapping(source = "pig.name",target = "name"),
            @Mapping(source = "pig.age",target = "age"),
        	// 可以指明pig.age
            @Mapping(source = "person.name",target = "personName")
    })
    PigInfoDto from (Pig pig, Person person);
}

2. 调用Mapper

package space.goldchen.mapstruct.main;

import space.goldchen.mapstruct.domain.Person;
import space.goldchen.mapstruct.domain.Pig;
import space.goldchen.mapstruct.service.dto.PigDto;
import space.goldchen.mapstruct.service.dto.PigInfoDto;
import space.goldchen.mapstruct.service.mapstruct.PigInfoMapper;
import space.goldchen.mapstruct.service.mapstruct.PigMapper;

/**
 * @author goldchen
 * @create 2022-08-12 9:15
 */
public class Test {
    public static void main(String[] args) {
        Pig pigOne = new Pig();
        pigOne.setId(1L);
        pigOne.setName("pigOne");
        pigOne.setAge(2);
        PigDto dto = PigMapper.MAPPER.from(pigOne);
        System.out.println(dto);

        System.out.println();
        Person person = new Person();
        person.setName("我是主人");
        PigInfoDto infoDto = PigInfoMapper.MAPPER.from(pigOne, person);
        System.out.println(infoDto);

    }
}

五、spring容器使用

1. 创建Mapper

改造Mapper,指定@Mapper(componentModel = “spring”,unmappedTargetPolicy = ReportingPolicy.IGNORE)

去掉之前MAPPER的定义

package space.goldchen.mapstruct.service.mapstruct;

import space.goldchen.mapstruct.domain.Pig;
import space.goldchen.mapstruct.service.dto.PigDto;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;

/**
 * @author goldchen
 * @create 2022-08-12 9:07
 */
// @Mapper
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface PigMapper {
    // public static PigMapper MAPPER = Mappers.getMapper(PigMapper.class);
    @Mappings({
            @Mapping(source = "id",target = "id"),
            @Mapping(source = "name",target = "name2"),
            @Mapping(source = "age",target = "age2")
    })
    public PigDto from(Pig pig);
}

package space.goldchen.mapstruct.service.mapstruct;

import space.goldchen.mapstruct.domain.Person;
import space.goldchen.mapstruct.domain.Pig;
import space.goldchen.mapstruct.service.dto.PigInfoDto;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;

/**
 * @author goldchen
 * @create 2022-08-12 9:54
 */
// @Mapper
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface PigInfoMapper {
    // PigInfoMapper MAPPER = Mappers.getMapper(PigInfoMapper.class);
    @Mappings({
            @Mapping(source = "pig.id",target = "id"),
            @Mapping(source = "pig.name",target = "name"),
            @Mapping(source = "pig.age",target = "age"),
            @Mapping(source = "person.name",target = "personName")
    })
    PigInfoDto from (Pig pig, Person person);
    
    /**
     * 反转转换的注解
     * @param dto
     * @return po
     */
    @InheritInverseConfiguration
    Pig convert(PigInfoDto dto);
}

2. 调用Mapper

package space.goldchen.mapstruct.service.mapstruct;

import space.goldchen.mapstruct.domain.Person;
import space.goldchen.mapstruct.domain.Pig;
import space.goldchen.mapstruct.service.dto.PigDto;
import space.goldchen.mapstruct.service.dto.PigInfoDto;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;

/**
 * 使用 springboot 的单元测试, 如果单元测试报错,试试设置webEnvironment
 * @author goldchen
 * @create 2022-08-12 10:28
 */
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class PigInfoMapperTest {

    @Resource
    private PigInfoMapper pigInfoMapper;
    @Resource
    private PigMapper pigMapper;

    @Test
    void from() {
        Pig pigTwo = new Pig();
        pigTwo.setId(2L);
        pigTwo.setName("pigTwo");
        pigTwo.setAge(2);
        Person person = new Person();
        person.setName("pigTow主人");
        PigInfoDto infoDto = pigInfoMapper.from(pigTow, person);
        Assertions.assertNotNull(infoDto);
        Pig pig = pigInfoMapper.convert(infoDto);
        Assertions.assertNotNull(pig);
    }

    @Test
    void from2() {
        Pig pigTwo = new Pig();
        pigTwo.setId(2L);
        pigTwo.setName("pigTwo");
        pigTwo.setAge(2);
        PigDto pigDto = pigMapper.from(pigTwo);
        Assertions.assertNotNull(pigDto);
    }
    
}

六、 父接口BaseMapper的使用(推荐使用)

1. 编写BaseMapper

package space.goldchen.mapstruct.mapper;

import java.util.List;

/**
 * 转换对象的属性名称一致时,可以省略Mappings的对应关系设置,使用泛型比较合适
 * mapstruct 公共类
 * 
 */
public interface BaseMapper<D, E> {

    /**
     * entity转 DTO
     *
     * @param entity
     * @return
     */
    D toDto(E entity);

    /**
     * DTO 转 entity
     *
     * @param dto
     * @return
     */
    E toEntity(D dto);

    /**
     * entity集合 转 DTO集合
     *
     * @param entityList
     * @return
     */
    List<D> toDto(List<E> entityList);

    /**
     * DTO集合 转 entity集合
     *
     * @param dtoList
     * @return
     */
    List<E> toEntity(List<D> dtoList);
}

2. 编写mapper

package space.goldchen.mapstruct.mapper;

import org.mapstruct.Mapper;
import org.mapstruct.ReportingPolicy;
import space.goldchen.mapstruct.dto.PigDto;
import space.goldchen.mapstruct.po.Pig;

/**
 * Pig2 MAPPER 继承 BaseMapper
 */
@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface Pig2Mapper extends BaseMapper<PigDto,Pig> {
}

3. 调用测试

package space.goldchen.mapstruct.mapper;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.util.Assert;
import space.goldchen.mapstruct.dto.PigDto;
import space.goldchen.mapstruct.po.Pig;

import javax.annotation.Resource;

import java.util.ArrayList;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
class PigMapperTest {

    @Resource
    private PigMapper pigMapper;

    @Resource
    private Pig2Mapper pig2Mapper;
    @Test
    void toDto() {
        Pig pig = new Pig();
        pig.setId(1L);
        pig.setName("my pig 1");

        PigDto pigDto = pigMapper.toDto(pig);
        //PigDto(id=1, name=my pig 1, age=null)
        System.out.println(pigDto);
    }

    @Test
    void testPig2toDto(){
        Pig pig = new Pig();
        pig.setId(2L);
        pig.setName("pig2");
        // toDto
        PigDto pigDto = pig2Mapper.toDto(pig);
        System.out.println(pigDto);
        // toEntity
        Pig pigByDto = pig2Mapper.toEntity(pigDto);
        System.out.println(pigByDto);
        // list to dtoList
        List<Pig> pigList = new ArrayList<>();
        pigList.add(pig);
        pigList.add(pigByDto);
        List<PigDto> pigDtos = pig2Mapper.toDto(pigList);
        System.out.println(pigDtos);

        // list to entityList
        List<Pig> pigListByDto = pig2Mapper.toEntity(pigDtos);
        System.out.println(pigListByDto);
    }
}

看到这里,一般开发就够用了,时间充裕的话,可以继续看

七、更多细节

1. 设置默认值

@Mapping(source = "person.name",target = "personName",defaultValue = "默认值")

2. 使用表达式

// 目前java是唯一受支持的语言,达式必须以Java表达式的形式给出
// 注意: 这个属性不能与source()、defaultValue()、defaultExpression()、
// qualifiedBy()、qualifiedByName()或constant()一起使用。
@Mapping(target = "describe", source = "describe", defaultValue = "默认值")
@Mapping(target = "createTime",expression = "java(new java.util.Date())")
PersonDTO conver(Person person);
@Mapping(target = "created",expression = "java(cn.hutool.core.date.DateTime.now())")

3. 类中的子类转换

// uses 成员类,子类
@Mapper(componentModel = "spring", uses = {Log3InnerMapper.class},
        unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface Log3Mapper extends BaseMapper<Log3DTO, Log3> {

}

4. Map的转换

// MapMapping  map集合使用
@Mapper
 public interface SimpleMapper {
       @MapMapping(valueDateFormat = "dd.MM.yyyy")
       Map<String, String> longDateMapToStringStringMap(Map<Long, Date> source);
 }

5. 逆转换

// 使用注释`@InheritInverseConfiguration`表示方法应继承相应反向方法的反向配置
@Mapping(target = "age",source = "age", numberFormat = "#0.00")
PersonDTO conver(Person person);

@InheritInverseConfiguration
Person conver(PersonDTO dto);

参考资料:

  1. 带我入门:https://www.jianshu.com/p/3f20ca1a93b0
  2. 内容细化:https://blog.csdn.net/qq_44732146/article/details/119968376

你可能感兴趣的:(Java,Java,springboot,java,springboot,预编码)