做注册任务的网站有哪些,注册免费的网站,网站开发看掉一些功能,网络工程师证书有哪些mapstruct核心技术学习 简介入门案例maven依赖 IDEA插件单一对象转换测试结果 mapping属性Spring注入的方式测试 集合的映射set类型的映射测试map类型的映射测试 MapMappingkeyDateFormatvalueDateFormat 枚举映射基础入门 简介
在工作中#xff0c;我们经常要进行各种对象之… mapstruct核心技术学习 简介入门案例maven依赖 IDEA插件单一对象转换测试结果 mapping属性Spring注入的方式测试 集合的映射set类型的映射测试map类型的映射测试 MapMappingkeyDateFormatvalueDateFormat 枚举映射基础入门 简介
在工作中我们经常要进行各种对象之间的转换。 PO: persistent object持久对象对应数据库中的一条 VO: view object表现层对象最终返回给前端的对象 DTO:data transfer object数据传输对象如dubbo服务之间的传输的对象 po、vo、dto的详细介绍 如果这些对象的属性名相同还好可以使用如下工具类赋值 Spring BeanUtils Cglib BeanCopier 避免使用Apache BeanUtils,性能较差 如果属性名不同呢如果是将多个PO对象合并成一个VO对象呢好在有MapStruct可以帮助我们快速转换 mapstruct官网 mapstruct技术文档
入门案例
maven依赖 propertiesjava.version1.8/java.versionorg.mapstruct.version1.5.5.Final/org.mapstruct.version
/properties
dependenciesdependencygroupIdorg.mapstruct/groupIdartifactIdmapstruct/artifactIdversion${org.mapstruct.version}/version/dependencydependencygroupIdorg.mapstruct/groupIdartifactIdmapstruct-processor/artifactIdversion${org.mapstruct.version}/version/dependency
/dependencies IDEA插件
IDEA中搜索MapStruct Support插件进行安装安装成功后重启IDEA。
单一对象转换
import lombok.Data;
import lombok.experimental.Accessors;Data
Accessors(chain true)
public class CarDTO {private String make;private int seatCount;private String type;
}import lombok.Data;
import lombok.experimental.Accessors;Data
Accessors(chain true)
public class Car {private String make;private int numberOfSeats;
}import com.example.demo.dto.CarDTO;
import com.example.demo.po.Car;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;Mapper
public interface CarMapper {CarMapper instance Mappers.getMapper(CarMapper.class);/*** 表达式需要自动提示的话需要安装IDEA插件mapstruct support* param car* return*/Mapping(source numberOfSeats,target seatCount)Mapping(target type,expression java(car.getMake()))CarDTO carToCarDto(Car car);
}import com.example.demo.dto.CarDTO;
import com.example.demo.mapper.CarMapper;
import com.example.demo.po.Car;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;RunWith(SpringRunner.class)
SpringBootTest(webEnvironment SpringBootTest.WebEnvironment.RANDOM_PORT, classes {DemoApplication.class})
public class ApplicationTest {Testpublic void test() {CarMapper instance CarMapper.instance;Car car new Car();car.setMake(中国).setNumberOfSeats(1000);CarDTO carDTO instance.carToCarDto(car);System.out.println(carDTO);}
}测试结果 项目结构图 在target文件夹下生成了CarMapperImpl.java
package com.example.demo.mapper;import com.example.demo.dto.CarDTO;
import com.example.demo.po.Car;
import javax.annotation.Generated;Generated(value org.mapstruct.ap.MappingProcessor,date 2023-11-08T23:35:280800,comments version: 1.5.5.Final, compiler: javac, environment: Java 1.8.0_131 (Oracle Corporation)
)
public class CarMapperImpl implements CarMapper {Overridepublic CarDTO carToCarDto(Car car) {if ( car null ) {return null;}CarDTO carDTO new CarDTO();carDTO.setSeatCount( car.getNumberOfSeats() );carDTO.setMake( car.getMake() );carDTO.setType( car.getMake() );return carDTO;}
}
mapping属性 /*** Mappings 一组映射关系值为一个数组元素为Mapping* Mapping 一一对应关系* source:源属性* target:目标属性赋值的过程是把源属性赋值给目标属性* dateFormat:用于源属性是Date,转换为String* numberFormat:用户数值类型与String类型之间的转* constant: 常量* expression:使用表达式进行属性之间的转换* ignore:忽略某个属性的赋值* qualifiedByName: 自定义的方法赋值* defaultValue:默认值* defaultExpression 如果源数据没有设置的时候可以指定相关表达式进行处理* 基本数据类型与包装类可以自动映射* MappingTaget 用在方法参数的前面使用此注解源对象同时也会作为目标对象用于更新* InheritConfiguration 指定映射方法* InheritInverseConfiguration 表示方法继承相应的反向方法的反向配置* param car 入参* return 返回结果*/package com.example.demo.entity;import lombok.Data;
import lombok.experimental.Accessors;Data
Accessors(chain true)
public class CarBrand {private String carBrand;
}
package com.example.demo.entity;import lombok.Data;
import lombok.experimental.Accessors;Data
Accessors(chain true)
public class Brand {private String brandName;}
package com.example.demo.entity;import lombok.Data;
import lombok.experimental.Accessors;Data
Accessors(chain true)
public class CarDto {private String make;private int seatCount;private String type;private CarBrand carBrand;private String date;private String price;private String extral;
}
package com.example.demo.entity;import lombok.Data;
import lombok.experimental.Accessors;import java.math.BigDecimal;
import java.util.Date;Data
Accessors(chain true)
public class Car {private String make;private int numberOfSeats;private Brand brand;private Date date;private BigDecimal price;}package com.example.demo.entity;import org.mapstruct.*;import static org.mapstruct.MappingConstants.ComponentModel.SPRING;/*** Mapper 表示该接口作为映射接口编译时MapStruct处理器的入口* componentModel 主要是指定实现类的类型一般用到两个* default默认可以通过 Mappers.getMapper(Class) 方式获取实例对象* spring在接口的实现类上自动添加注解 Component可通过 Autowired 方式注入* uses 外部引入的转换类*/
Mapper(componentModel SPRING)
public interface CarMapper {/*** Mappings 一组映射关系值为一个数组元素为Mapping* Mapping 一一对应关系* source:源属性* target:目标属性赋值的过程是把源属性赋值给目标属性当目标属性和源属性一致时候source和target可以省略不写* dateFormat:用于源属性是Date,转换为String* numberFormat:用户数值类型与String类型之间的转* constant: 常量* expression:使用表达式进行属性之间的转换* ignore:忽略某个属性的赋值* qualifiedByName: 自定义的方法赋值* defaultValue:默认值* defaultExpression 如果源数据没有设置的时候可以指定相关表达式进行处理* 基本数据类型与包装类可以自动映射* MappingTaget 用在方法参数的前面使用此注解源对象同时也会作为目标对象用于更新* InheritConfiguration 指定映射方法* InheritInverseConfiguration 表示方法继承相应的反向方法的反向配置* param car 入参* return 返回结果*/Mappings({Mapping(source date,target date,dateFormat yyyy-MM-dd HH:mm:ss),Mapping(source price,target price,numberFormat 0.00),Mapping(source numberOfSeats,target seatCount),Mapping(target type,constant hello type),Mapping(source brand,target carBrand,qualifiedByName {brand2CarBrandV2})})CarDto carToCarDtoV2(Car car);/*** Named 定义类/方法的名称* param brand* return*/Named(brand2CarBrandV2)Mappings({Mapping(source brandName,target carBrand)})CarBrand brand2CarBrandV2(Brand brand);
}
package com.example.demo;import com.example.demo.entity.Brand;
import com.example.demo.entity.Car;
import com.example.demo.entity.CarDto;
import com.example.demo.entity.CarMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.math.BigDecimal;
import java.util.Date;RunWith(SpringRunner.class)
SpringBootTest(webEnvironment SpringBootTest.WebEnvironment.RANDOM_PORT, classes {DemoApplication.class})
public class CarMapperTest {Autowiredprivate CarMapper carMapper;Testpublic void test() {Car car new Car();car.setMake(from source).setNumberOfSeats(100).setBrand(new Brand().setBrandName(保密)).setPrice(BigDecimal.valueOf(100.12345)).setDate(new Date());CarDto dto carMapper.carToCarDtoV2(car);System.out.println(dto);}
}
测试结果输出如下
CarDto(makefrom source, seatCount100, typehello type, carBrandCarBrand(carBrand保密), date2023-11-11 20:22:49, price100.12, extralnull)
Spring注入的方式
中声明INSTANCE的方式来进行调用之外MapStruct也同时支持Spring的依赖注入机制
package com.example.MapStructDemo.dto;import lombok.Data;
import lombok.experimental.Accessors;Data
Accessors(chain true)
public class CarDto {private String manufacturer;private int seatCount;
}
package com.example.MapStructDemo.po;import lombok.Data;
import lombok.experimental.Accessors;Data
Accessors(chain true)
public class Car {private String make;private int numberOfSeats;
}
package com.example.MapStructDemo.mapper;import com.example.MapStructDemo.dto.CarDto;
import com.example.MapStructDemo.po.Car;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;import static org.mapstruct.MappingConstants.ComponentModel.SPRING;/*** Mapper 只有在接口加上这个注解 MapStruct 才会去实现该接口* Mapper 里有个 componentModel 属性主要是指定实现类的类型一般用到两个* default默认可以通过 Mappers.getMapper(Class) 方式获取实例对象* SPRING在接口的实现类上自动添加注解 Component可通过 Autowired 方式注入*/
Mapper(componentModel SPRING)
public interface CarMapper {Mapping(target manufacturer,source make)Mapping(target seatCount,source numberOfSeats)CarDto carToCarDto(Car car);}
测试
package com.example.MapStructDemo;import com.example.MapStructDemo.dto.CarDto;
import com.example.MapStructDemo.mapper.CarMapper;
import com.example.MapStructDemo.po.Car;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;SpringBootTest
public class ApplicationTests {Autowiredprivate CarMapper carMapper;Testpublic void contextLoads() {Car car new Car();car.setMake(中国).setNumberOfSeats(1000);CarDto carDto carMapper.carToCarDto(car);System.out.println(测试结果);System.out.println(carDto);}} 集合的映射
set类型的映射
package com.example.MapStructDemo.mapper;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import java.util.Set;
import static org.mapstruct.MappingConstants.ComponentModel.SPRING;Mapper(componentModel SPRING)
public interface CarMapper {/*** 集合的映射* param set 入参* return SetString*/SetString integerSetToStringSet(SetInteger set);
}
CarMapper的实现类CarMapperImpl会生成如下代码集合set为null的时候,默认返回null
测试
package com.example.MapStructDemo;import com.example.MapStructDemo.mapper.CarMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.HashSet;
import java.util.Set;SpringBootTest
public class ApplicationTests {Autowiredprivate CarMapper carMapper;Testpublic void test(){SetInteger set new HashSet();for (int i0;i10;i){set.add(i);}SetString strings carMapper.integerSetToStringSet(set);System.out.println(集合类型的测试);strings.forEach(System.out::println);}
}
测试结果如下
map类型的映射
package com.example.MapStructDemo.mapper;import org.mapstruct.MapMapping;
import org.mapstruct.Mapper;import java.util.Date;
import java.util.Map;import static org.mapstruct.MappingConstants.ComponentModel.SPRING;Mapper(componentModel SPRING)
public interface SourceTargetMapper {/*** map类型的映射* param source 入参* return MapString, String* map中value的值是Date类型的转换为String类型*/MapMapping(valueDateFormat dd.MM.yyyy)MapString, String longDateMapToStringStringMap(MapLong, Date source);
}
map映射的实现类SourceTargetMapperImpl
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package com.example.MapStructDemo.mapper;import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.stereotype.Component;Component
public class SourceTargetMapperImpl implements SourceTargetMapper {public SourceTargetMapperImpl() {}public MapString, String longDateMapToStringStringMap(MapLong, Date source) {if (source null) {return null;} else {MapString, String map new LinkedHashMap(Math.max((int)((float)source.size() / 0.75F) 1, 16));Iterator var3 source.entrySet().iterator();while(var3.hasNext()) {Map.EntryLong, Date entry (Map.Entry)var3.next();String key (new DecimalFormat()).format(entry.getKey());String value (new SimpleDateFormat(dd.MM.yyyy)).format((Date)entry.getValue());map.put(key, value);}return map;}}
}
测试
package com.example.MapStructDemo;import com.example.MapStructDemo.mapper.SourceTargetMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.time.LocalDate;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;SpringBootTest
public class SourceTargetMapperTests {Autowiredprivate SourceTargetMapper sourceTargetMapper;Testpublic void test() {MapLong, Date map new HashMap();map.put(1L, new Date());System.out.println(map);System.out.println(map类型的映射);MapString, String result sourceTargetMapper.longDateMapToStringStringMap(map);System.out.println(result);}
}
测试结果
MapMapping
配置的是MapString,String和MapLong,Date之间的转换
keyDateFormat
map中key的类型是从Date到String类型的转换
valueDateFormat
map中value的类型从Date到String类型的转换
枚举映射
基础入门
package com.example.MapStructDemo.enums;import lombok.AllArgsConstructor;
import lombok.Getter;AllArgsConstructor
Getter
public enum OrderType {EXTRA,STANDARD,NORMAL
}
package com.example.MapStructDemo.enums;import lombok.AllArgsConstructor;
import lombok.Getter;AllArgsConstructor
Getter
public enum ExternalOrderType {SPECIAL,DEFAULT
}
package com.example.MapStructDemo.mapper;import com.example.MapStructDemo.enums.ExternalOrderType;
import com.example.MapStructDemo.enums.OrderType;
import org.mapstruct.Mapper;
import org.mapstruct.ValueMapping;
import org.mapstruct.ValueMappings;import static org.mapstruct.MappingConstants.ComponentModel.SPRING;Mapper(componentModel SPRING)
public interface OrderMapper {/*** 枚举类型映射* param orderType 入参* return ExternalOrderType*/ValueMappings({ValueMapping(target SPECIAL,source EXTRA),ValueMapping(target DEFAULT,source STANDARD),ValueMapping(target DEFAULT,source NORMAL)})ExternalOrderType orderTypeToExternalOrderType(OrderType orderType);
}
OrderMapper的实现类
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package com.example.MapStructDemo.mapper;import com.example.MapStructDemo.enums.ExternalOrderType;
import com.example.MapStructDemo.enums.OrderType;
import org.springframework.stereotype.Component;Component
public class OrderMapperImpl implements OrderMapper {public OrderMapperImpl() {}public ExternalOrderType orderTypeToExternalOrderType(OrderType orderType) {if (orderType null) {return null;} else {ExternalOrderType externalOrderType;switch (orderType) {case EXTRA:externalOrderType ExternalOrderType.SPECIAL;break;case STANDARD:externalOrderType ExternalOrderType.DEFAULT;break;case NORMAL:externalOrderType ExternalOrderType.DEFAULT;break;default:throw new IllegalArgumentException(Unexpected enum constant: orderType);}return externalOrderType;}}
}
package com.example.MapStructDemo;import com.example.MapStructDemo.enums.ExternalOrderType;
import com.example.MapStructDemo.enums.OrderType;
import com.example.MapStructDemo.mapper.OrderMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;SpringBootTest
public class OrderMapperTest {Autowiredprivate OrderMapper orderMapper;Testpublic void test1() {System.out.println(测试结果);OrderType orderType OrderType.EXTRA;ExternalOrderType externalOrderType orderMapper.orderTypeToExternalOrderType(orderType);System.out.println(externalOrderType);}
}
测试结果