1. Performance comparison of major object mapping frameworks

tool implementation disadvantages instructions
mapstruct Getter/setter methods You need to understand annotation and configuration item syntax JSR269 annotation processor automatically generates Java Bean conversion code at compile time, which supports configurable and extensibility
orika Dynamic generation of bytecode The first invocation takes a long time and has moderate performance The bytecode of the Bean map is generated using the Javassist class library, and the bytecode file that performs the generation is directly loaded
Spring BeanUtils Reflection mechanism Attribute conversions with the same name but different types are not supported
Apache BeanUtils Reflection mechanism Compile-time exceptions need to be handled with the worst performance
dozer Reflection mechanism Performance is poor Assign attributes using the set(Object obj, Object Value) method of the Field class under the Reflect package
BeanCopier Reflection mechanism \1. BeanCopier copies only properties with the same name and type. Even primitive types cannot be converted to their corresponding wrapper types; Use ASM’s MethodVisitor to write the GET /set methods for each attribute directly

In terms of performance: Mapstruct is definitely the best, followed by Spring BeanUtils> Orika >BeanCopier> Dozer > Apache BeanUtils

2. Use of MapStruct

2.1 introduction of POM

< the dependency > < groupId > org. Mapstruct < / groupId > < artifactId > mapstruct < / artifactId > < version > 1.3.0. The Final < / version > <scope>provided</scope> </dependency>Copy the code

2.2. Single bean mapping

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

@Mapper(componentModel = "spring")
public interface OrderConvert {

    @Mapping(source = "id", target = "orderId")
    @Mapping(source = "createTime", target = "orderTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
    OrderDTO from(Order order);

}
Copy the code

The test code

@test public void Test () {Order Order = order.builder ().id().buyerphone ("13707318123").buyeraddress ("中电软件园").buyeraddress ("中电软件园") .amount(10000L) .payStatus(1) .createTime(LocalDateTime.now()) .build(); OrderConvert orderConvert = Mappers.getMapper(OrderConvert.class); OrderDTO orderDTO = orderConvert.from(order); System.out.println("order: " + order); System.out.println("orderDTO: " + orderDTO); }Copy the code

2.3 Mapping of multiple beans

@mapper (componentModel = "spring") public interface GoodInfoConvert {/** Long => String implicit type conversion */ @mapping (source =) "Good. id", target = "goodId") */ @mapping (source = "type.name", target = "typeName") /** Attribute name is different */ @mapping (source = "good.title", Target = "goodName") / @mapping (source = "good.price", target = "goodPrice") GoodInfoDTO from(GoodInfo good, GoodType type); }Copy the code

2.4. Parameter meaning mapping

import org.mapstruct.Mapper; import org.mapstruct.Mapping; import java.time.LocalDate; import java.time.LocalDateTime; @Mapper(imports = {CustomMapping.class}) public interface StudentConvert { @Mapping(source = "id", target = "studentId") @Mapping(source = "name", target = "studentName") @Mapping(source = "age", target = "age") @Mapping(target = "ageLevel", expression = "java(CustomMapping.ageLevel(student.getAge()))") @Mapping(target = "sexName", expression = "java(CustomMapping.sexName(student.getSex()))") @Mapping(source = "admissionTime", target = "admissionDate", dateFormat = "yyyy-MM-dd") StudentDTO from(Student student); default LocalDate map(LocalDateTime time) { return time.toLocalDate(); }}Copy the code

Custom mapping class

Public Class CustomMapping {static Final String[] SEX = {" female ", "male "," unknown "}; public static String sexName(Integer sex) { if (sex < 0 && sex > 2){ throw new IllegalArgumentException("invalid sex: " + sex); } return SEX[sex]; } public static String ageLevel(Integer age) {if (age < 18) {return "juvenile "; } else if (age >= 18 && age < 30) {return "youth "; } else if (age >= 30 && age < 60) {return "middle age "; } else {return "old "; }}}Copy the code

3. Use of ORIka

3.1 introduction of pom

< the dependency > < groupId > ma. Glasnost. Orika < / groupId > < artifactId > orika - core < / artifactId > < version > 1.5.2 < / version > </dependency>Copy the code

3.2. Initialize the instance

package tech.chenxing.deploy.configuration; import ma.glasnost.orika.MapperFactory; import ma.glasnost.orika.impl.DefaultMapperFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MapperConfig { @Bean public MapperFactory mapperFactory() { return new DefaultMapperFactory.Builder().build(); }}Copy the code

3.3. Configure the mapping object

Define converter

public class FlowDocDOConverter extends CustomMapper<FlowDoc, FlowDocBean> { @Autowired private DocInfoMapperExt docInfoMapperExt; @Override public void mapAtoB(FlowDoc flowDocDO, FlowDocBean flowDocBean, MappingContext context) { if (StringUtils.isNotBlank(flowDocDO.getDocUuid())) { DocInfo docInfoDO = docInfoMapperExt.getByUUID(flowDocDO.getDocUuid()); ValidationUtil.assertNull( docInfoDO, new BizFlowManagerException( BizFlowManagerBaseResultCodeEnum.FLOW_NOT_EXISTS, flowDocDO.getDocUuid())); flowDocBean.setId(docInfoDO.getId()); flowDocBean.setFileId(docInfoDO.getFileId()); flowDocBean.setName(docInfoDO.getName()); flowDocBean.setDocPassword(docInfoDO.getDocPassword()); flowDocBean.setDocSource(docInfoDO.getDocSource()); flowDocBean.setEncryption(docInfoDO.getEncryption()); flowDocBean.setGmtCreate(flowDocDO.getGmtCreate()); flowDocBean.setGmtModified(flowDocDO.getGmtModified()); }}}Copy the code

Injection converter

package tech.chenxing.deploy.configuration; import ma.glasnost.orika.MapperFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; @Component public class MapperInit { @Autowired private MapperFactory mapperFactory; @Autowired private FlowDocDOConverter flowDocDOConverter; Class (userto.class).field("docUuid", "DocId ").bydefault () // Remaining field mapping.customize(flowDocDOConverter).register(); }}Copy the code

Code using

public xxx queryuser() {
        List<User> userList =
                userMapperExt.queryUser();
        List<UserDTO> userDTOList =
                mapperFactory.getMapperFacade().mapAsList(userList, UserDTO.class);
        QueryFlowDocResult queryFlowDocResult = new QueryFlowDocResult();
    }
Copy the code

Copyright notice: This article is the original blog, in accordance with CC 4.0 BY+SA copyright agreement, please attach the original source link and this statement. Link to this article: www.94rg.com/article/179…