英文:
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) {
// 执行映射
}
}
让我们理解这个示例。在这个示例中,DTO1
和 DTO2
都有一个名为 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
)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论