定义自定义的MapStruct映射器,而无需定义所有字段的映射。

huangapple go评论66阅读模式
英文:

Define custom MapStruct mapper without having to define mapping of all fields

问题

以下是翻译好的代码部分:

// 使用MapStruct进行映射
@Mapping(target = "desiredName", source = "notDesiredName")
// 等等
DTO1 toDto1(Dto2 dto2);

// 若要对Dto2中的某一属性进行函数处理
default DTO1 toDto1(Dto2 dto2) {
    // ...
    dto1.setSomething(myFunction(dto.getSomething()));
    // ...
}
英文:

Suppose I have two DTOs which I wish to map with MapStruct, DTO1 and DTO2 have largely identical fields differing only in naming and I wish to map them all from one to the other. With MapStruct I could just do:

@Mapping(target = "desiredName", source = "notDesiredName")
// etc
DTO1 toDto1(Dto2 dto2);

but suppose I have just one property within Dto2 which I would like to pass through a function first. I know I could do:

default DTO1 toDto1(Dto2 dto2) {
    ...
    dto1.setSomething(myFunction(dto.getSomething)
    ...
}

How can I avoid having to rote define every other property conversion?

答案1

得分: 1

以下是您要翻译的内容:

默认情况下,Mapstruct将自动传输所有具有相同名称/类型的字段。为了干预自动执行的操作,可以使用@AfterMapping注解,仅编写异常情况的代码。 (或使用@BeforeMapping

import org.mapstruct.AfterMapping;
import org.mapstruct.Mapper;
import org.mapstruct.MappingTarget;

import com.example.demo.dto.Dto1;
import com.example.demo.dto.Dto2;

@Mapper
public abstract class DtoMapper {

	@Mapping(target = "desiredName", source = "notDesiredName")

    @AfterMapping
    protected void interveneWithSomethingThatChanges (Dto1 dto1, @MappingTarget Dto2 dto2) {
    	dto2.somethingThatChanges = dto1.somethingThatChanges + ": changed";
    }

    public abstract Dto2 toDto2(Dto1 dto1);
}

其余代码如下:

MapperMain.java

import org.mapstruct.factory.Mappers;

import com.example.demo.dto.Dto1;
import com.example.demo.dto.Dto2;
import com.example.demo.mapper.DtoMapper;

public class MapperMain {

    public static void main(String[] args) {
        final DtoMapper mapper
          = Mappers.getMapper(DtoMapper.class);

        Dto1 dto1 = new Dto1("somethingThatChanges", "somethingThatStaysTheSame", "somethingElseThatStaysTheSame");
        Dto2 dto2 = mapper.toDto2(dto1);

        System.out.println(dto2);
    }
}

Output:

Dto2 [somethingThatChanges=somethingThatChanges: changed, somethingThatStaysTheSame=somethingThatStaysTheSame, desiredName=somethingElseThatStaysTheSame]

Dto1.java

public class Dto1 {
    public String somethingThatChanges;
    public String somethingThatStaysTheSame;
    public String notDesiredName;

    public Dto1(String somethingThatChanges, String somethingThatStaysTheSame, String notDesiredName) {
        this.somethingThatChanges = somethingThatChanges;
        this.somethingThatStaysTheSame = somethingThatStaysTheSame;
        this.notDesiredName = notDesiredName;
    }
}

Dto2.java

public class Dto2 {
    @Override
    public String toString() {
        return "Dto2 [somethingThatChanges=" + somethingThatChanges + ", somethingThatStaysTheSame="
                + somethingThatStaysTheSame + ", desiredName=" + desiredName + "]";
    }
    public String somethingThatChanges;
    public String somethingThatStaysTheSame;
    public String desiredName;
}
英文:

By default Mapstruct will automatically transfer all the fields with the same name/type. In order to intervene in what is done automatically use the @AfterMapping annotation and code only the exceptions. (or use @BeforeMapping)

import org.mapstruct.AfterMapping;
import org.mapstruct.Mapper;
import org.mapstruct.MappingTarget;

import com.example.demo.dto.Dto1;
import com.example.demo.dto.Dto2;

@Mapper
public abstract class DtoMapper {

	@Mapping(target = "desiredName", source = "notDesiredName")

    @AfterMapping
    protected void interveneWithSomethingThatChanges (Dto1 dto1, @MappingTarget Dto2 dto2) {
    	dto2.somethingThatChanges = dto1.somethingThatChanges + ": changed";
    }

    public abstract Dto2 toDto2(Dto1 dto1);
}

The remaining code is as follows:

MapperMain.java

import org.mapstruct.factory.Mappers;

import com.example.demo.dto.Dto1;
import com.example.demo.dto.Dto2;
import com.example.demo.mapper.DtoMapper;

public class MapperMain {

public static void main(String[] args) {
    final DtoMapper mapper
      = Mappers.getMapper(DtoMapper.class);
    
    Dto1 dto1 = new Dto1("somethingThatChanges", "somethingThatStaysTheSame", "somethingElseThatStaysTheSame");
	Dto2 dto2 = mapper.toDto2(dto1);
	
	System.out.println(dto2);


}

}

Output:

Dto2 [somethingThatChanges=somethingThatChanges: changed, somethingThatStaysTheSame=somethingThatStaysTheSame, desiredName=somethingElseThatStaysTheSame]

Dto1.java

public class Dto1 {
public String somethingThatChanges;
public String somethingThatStaysTheSame;
public String notDesiredName;

public Dto1(String somethingThatChanges, String somethingThatStaysTheSame, String notDesiredName) {
	this.somethingThatChanges = somethingThatChanges;
	this.somethingThatStaysTheSame = somethingThatStaysTheSame;
	this.notDesiredName = notDesiredName;
}
}

Dto2.java

public class Dto2 {
@Override
public String toString() {
	return "Dto2 [somethingThatChanges=" + somethingThatChanges + ", somethingThatStaysTheSame="
			+ somethingThatStaysTheSame + ", desiredName=" + desiredName + "]";
}
public String somethingThatChanges;
public String somethingThatStaysTheSame;
public String desiredName;
}

答案2

得分: 0

如果您有一个自定义函数来映射特定属性,您可以使用qualifiers

例如:

@Mapper
public interface MyMapper {

    @Mapping(target = "something", qualifiedByName = "customSomething")
    DTO1 toDto1(Dto2 dto2);

    @Named("customSomething")
    default String mapSomething(String value) {
         // 执行映射
    }
}

让我们理解这个示例。在这个示例中,DTO1DTO2 都有一个名为 something 的字段。因此,我们只需要定义 Mapping#target(当目标和源匹配时,Mapping#source 已过时)。

接下来是我们希望以某种特殊的方式映射这个字段的事实。我们使用 Mapping#qualifiedByName 来定义这一点。这告诉 MapStruct 查找一个用 @Named("customSomething") 注解的自定义映射方法。

mapSomething 方法是一个用 @Named("customSomething") 注解的自定义方法,这告诉 MapStruct 这是一个特殊的映射方法,只有在用户明确请求它时才应使用(使用 Mapping#qualifiedBy)。

英文:

If you have a custom function to map a specific property you can use qualifiers.

e.g.

@Mapper
public interface MyMapper {


    @Mapping(target = "something", qualifiedByName = "customSomething")
    DTO1 toDto1(Dto2 dto2);

    @Named("customSomething")
    default String mapSomething(String value) {
         // perform mapping
    }
}

Let's digest the example. In this example both DTO1 and DTO2 have a field named something. Therefore, we only need to define Mapping#target (Mapping#source is obsolete when target and source match).

Next is the fact that we want to perform some special way of mapping this field. We define this with Mapping#qualifiedByName. This tells MapStruct to look for a custom mapping method annotated with @Named("customSomething").

The mapSomething method is a custom method annotated with @Named("customSomething") this tells MapStruct that this is a special mapping method and it should only be used if the user has specifically requested it (using Mapping#qualifiedBy)

huangapple
  • 本文由 发表于 2023年4月6日 21:46:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/75950274.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定