Java object copy MapStruct

introduce

Object copy code can be generated at compile time. Simple to understand, functional positioning org.springframework.beans.BeanUtils.
Official website , GitHub-MapStruct .

getting Started

The maven project introduces dependencies:

  1. mapstruct: contains necessary annotations, such as @Mapping
  2. mapstruct-processor: Annotation processor, which automatically generates mapper implementations based on annotations
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
</dependency>
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
</dependency>

Actual combat:

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;

// 如果增加componentModel 增生成的实现类有注解@Component
@Mapper(componentModel = "spring")
public interface AccountConvert {
    
    

    AccountConvert INSTANCE = Mappers.getMapper(AccountConvert.class);

    @Mappings({
    
    
            @Mapping(target = "username", source = "userName")
            @Mapping(source = "userTypeEnum", target = "type")
			@Mapping(target = "createTime", expression = "java(com.java.mmzsblog.util.DateTransform.strToDate(source.getCreateTime()))"),

    })
    Account dto2Entity(AccountDTO dto);

	@Data
	private static class Account {
    
    
		private string username;
	}
	
	@Data   
  	private static class AccountDTO {
    
    
		private string userName;
	}

	@Getter
	@AllArgsConstructor
	public enum UserTypeEnum {
    
    
	    JAVA("000", "Java开发工程师"),
	    DB("001", "数据库管理员");	    
	    private String value;
	    private String title;
	}

Generate class files:

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2023-06-10T12:52:02+0800",
    comments = "version: 1.5.5.Final, compiler: javac, environment: Java 11.0.18 (Azul Systems, Inc.)"
)
public class AccountConvertImpl implements AccountConvert {
    
    
	@Override
    public Account dto2Entity(AccountDTO dto) {
    
    
        if (dto == null) {
    
    
            return null;
        }
        Account account = new Account();
        account.setUsername(dto.getUserName());
        return account;
    }
}

Spring Bean

When using the @Mapper annotation, if you make a note componentModel = "spring", you can AccountConvertuse it as a Spring Bean:

@Resource
private DrugConverter drugConverter;

insert image description here

principle

When the field types are inconsistent, MapStruct can automatically implement the type of type conversion:

  1. Basic types and their corresponding wrapper types
  2. Between the wrapper type of the basic type and the String type

In addition to the type conversion, you can specify the conversion by defining an expression.

annotation

  • @Mapper, used for interface classes, can be understood as defining a static class or Spring Bean class
  • @Mapping, specify the mapping relationship between source and target entity classes
  • @Mappings, a collection of multiple @Mappings
  • @MapMapping:
  • @BeanMapping:
  • @BeforeMapping & @AfterMapping: Similar to Junit's @BeforeTest and @AfterTest, do some processing before and after @Mapping
  • @InheritConfiguration:
  • @InheritInverseConfiguration: When there is already a DTO to PO interface method definition, and a PO to DTO interface is needed, this annotation can be used to save configuration and maintenance of information such as source, target, and dateFormat

data type mapping

MapStruct supports data type conversion between source and target attributes, and also provides automatic type conversion, applicable to:

  • Between primitive types and their corresponding wrapper classes
  • Between any basic type and any wrapper class, such as byte and Integer
  • Between all basic types and wrapper classes and String
  • Between enumeration and String
  • Between the Java large number type ( java.math.BigInteger, java.math.BigDecimal) and the Java basic type (including its wrapping class) and String.

For date conversion, you can use the dateFormat flag to specify the date format;
for digital conversion, you can use the numberFormat to specify the display format

enum map

combat

Record problems encountered in use

Internal error in the mapping processor: java.lang.NullPointerException

IDEA 2022.1.4 (Ultimate Edition) version, starting the application in Debug mode fails:

java: Internal error in the mapping processor: java.lang.NullPointerException
at org.mapstruct.ap.internal.processor.DefaultVersionInformation.createManifestUrl(DefaultVersionInformation.java:182)      at org.mapstruct.ap.internal.processor.DefaultVersionInformation.openManifest(DefaultVersionInformation.java:153)      at org.mapstruct.ap.internal.processor.DefaultVersionInformation.getLibraryName(DefaultVersionInformation.java:129)      at org.mapstruct.ap.internal.processor.DefaultVersionInformation.getCompiler(DefaultVersionInformation.java:122)
at org.mapstruct.ap.internal.processor.DefaultVersionInformation.fromProcessingEnvironment(DefaultVersionInformation.java:95)
at org.mapstruct.ap.internal.processor.DefaultModelElementProcessorContext.<init>(DefaultModelElementProcessorContext.java:54)
at org.mapstruct.ap.MappingProcessor.processMapperElements(MappingProcessor.java:264)
at org.mapstruct.ap.MappingProcessor.process(MappingProcessor.java:166)
at org.jetbrains.jps.javac.APIWrappers$ProcessorWrapper.process(APIWrappers.java:157)

Reference , solution: upgrade MapStruct pom dependencies, 1.4.0.Final-> current latest version 1.5.5.Final.

No target bean properties found: can’t map Collection element, Consider to declare/implement a mapping method

The application starts in Debug mode and reports an error:

java: No target bean properties found: can't map Collection element "DrugEsEntity drugEsEntity" to "DrugListVo drugListVo". Consider to declare/implement a mapping method: "DrugListVo map(DrugEsEntity value)".

Existing interface definitions:

@Mapper
public interface DrugConverter {
    
    
    DrugConverter INSTANCE = Mappers.getMapper(DrugConverter.class);
    
    List<DrugListVo> esToVos(List<DrugEsEntity> entities);
}

Solution, add interface:

DrugListVo esToVo(DrugEsEntity entity);

DrugConverterImplThis is evident in the generated code:
insert image description here

reference

MapStruct 1.5 release supports Map to Bean conversion

Guess you like

Origin blog.csdn.net/lonelymanontheway/article/details/120401779