我必须使用不同的属性名称将 List 映射到 List。
前任:
public class Object1 {
private String name;
//getters and setters
}
public class Object2 {
private String customerName;
//getters and setters
}
@Mapping(source="object1List.name" target="object2List.customerName"
List<Object2> toObject2(final List<Object1> object1List)
Run Code Online (Sandbox Code Playgroud)
我没有写我在哪里得到 Object1List 来简化。(我在一个方法的不同类中得到了它)
我一直在尝试这个,但 mapstruct 抱怨 object1List 是未知属性。有没有办法做到这一点?帮助表示赞赏。
Mapstruct 在编译阶段抛出了下一个错误:
ConfigsMapperImpl 不是抽象的,不会覆盖抽象方法 toConfigs(ConfigsDTO)
与此同时,MapStruct 很好地为所有其他方法生成代码。
我想这是因为Configobject 的字段多于ConfigsDTO.
@Mapper
public interface ConfigsMapper {
ConfigsMapper INSTANCE = Mappers.getMapper(ConfigsMapper.class);
ConfigsDTO ConfigsToConfigsDTO(Configs configs);
List<ConfigsDTO> toConfigsDTOs(List<Configs> configs);
@InheritInverseConfiguration
Configs toConfigs(ConfigsDTO configsDTO);
}
Run Code Online (Sandbox Code Playgroud) 就像标题中所说的,我在中有一个mapper接口src/test/java,它不是由mapstruct处理器生成的。
在同一项目中,src/main/java将生成所有映射器。这是预期的行为吗?
如何在测试源中生成映射器?
编辑(更多信息):
简化的Maven模块结构:
root_project
-> module_1
Run Code Online (Sandbox Code Playgroud)
的pom.xml root_project
<build>
<pluginManagement>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.1.0.Final</version>
</path>
</annotationProcessorPaths>
<compilerArgs>
<compilerArg>
-Amapstruct.defaultComponentModel=spring
</compilerArg>
</compilerArgs>
</configuration>
</plugin>
...
Run Code Online (Sandbox Code Playgroud)
的pom.xml module_1基本上是空的:
<dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<scope>compile</scope>
</dependency>
Run Code Online (Sandbox Code Playgroud) 我有带有字段的实体类:
我有带字段的 DTO 类:
如果我喜欢这样:
@Mappings({ @Mapping(source = "senderId", target = "sender.id"), @Mapping(source = "recipientId", target = "recipient.id") })
Run Code Online (Sandbox Code Playgroud)
Mapstruct 将生成如下代码:
public Entity toEntity(DTO) {
//...
entity.setSender( dtoToClient( dto ) );
entity.setRecipient( dtoToClient( dto ) );
//...
protected Client dtoToClient(Dto dto) {
Client client = new Client();
client.setId( dto.getRecipientId() ); // mapstruct takes recipient id for sender and recipient
return client;
}
}
Run Code Online (Sandbox Code Playgroud)
Mapstruct 为发件人和收件人而不是收件人 id 使用收件人 id 来创建客户端收件人和发件人 id 来创建客户端发件人。
所以我发现的更好的方法是使用就我所见并不那么优雅的表达式:
@Mappings({
@Mapping(target = …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用 mapstruct 将我的 DTO 映射到 protobuf 生成的类。此类包含地图,但这会导致异常:
java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableMap.putAll(Collections.java:1463)
Run Code Online (Sandbox Code Playgroud)
我不知道如何绕过这个。
这是我的映射器功能
@Mappings({
@Mapping(target = "profiles", source = "profiles"),
MyClassMessage.Builder convertToBuilder(MyClassDto myClassDto);
Run Code Online (Sandbox Code Playgroud)
它生成此代码
if ( builder.getProfiles() != null ) {
Map<String, Object> map = stringInterpreterProfileMapToStringInterpreterProfileMessageMap( interpreterSettingDto.getProfiles() );
if ( map != null ) {
builder.getProfiles().putAll( map ); // <-- this cause the exception
}
}
Run Code Online (Sandbox Code Playgroud)
但我认为它应该是这样的
if ( builder.getProfiles() != null ) {
Map<String, Object> map = stringInterpreterProfileMapToStringInterpreterProfileMessageMap( interpreterSettingDto.getProfiles() );
if ( map != null ) {
builder.putAllProfiles( map ); …Run Code Online (Sandbox Code Playgroud) 我在 Config 和 ConfigHeaders 之间有一对多的关系。这是配置映射器:
@Mapper(componentModel = "spring", uses = {UserMapper.class, ConfigHeadersMapper.class})
public interface ConfigMapper extends EntityMapper<ConfigDTO, Config> {
@Mapping(source = "user.id", target = "userId")
ConfigDTO toDto(Config config);
@Mapping(source = "userId", target = "user")
@Mapping(target = "messages", ignore = true)
Config toEntity(ConfigDTO configDTO);
default Config fromId(Long id) {
if (id == null) {
return null;
}
Config config = new Config();
config.setId(id);
return config;
}
}
Run Code Online (Sandbox Code Playgroud)
这是 ConfigHeadersMapper:
@Mapper(componentModel = "spring", uses = {ConfigMapper.class})
public interface ConfigHeadersMapper extends EntityMapper<ConfigHeadersDTO, ConfigHeaders> …Run Code Online (Sandbox Code Playgroud) 我有以下映射器
@Mapper
@Named("RoleBaseMapper")
public interface RoleBaseMapper {
@Mapping(target = "code", source = "name")
@Named("mapToBase")
RoleGuiBaseDto mapToBase(Role role);
@Named("MapListToBase")
List<RoleGuiBaseDto> mapListToBase(List<Role> roles);
}
Run Code Online (Sandbox Code Playgroud)
我期望的是,mapListToBase它将用于mapToBase映射列表中的每个条目。但是当我看到生成的代码时,我有以下内容
@Override
public List<RoleGuiBaseDto> mapListToBase(List<Role> roles) {
if ( roles == null ) {
return null;
}
List<RoleGuiBaseDto> list = new ArrayList<RoleGuiBaseDto>( roles.size() );
for ( Role role : roles ) {
list.add( roleToRoleGuiBaseDto( role ) );
}
return list;
}
protected RoleGuiBaseDto roleToRoleGuiBaseDto(Role role) {
if ( role == null ) {
return …Run Code Online (Sandbox Code Playgroud) 我想拥有一个Mapper同时包含create和update方法的类。为create方法生成的代码很好,但是在更新的情况下,仅当源中的属性不为null时,我才想在目标中设置属性。
我该怎么做mapStruct?
之所以会出现混乱,是因为nullValueMappingStrategy在Mapper或Mapping级别上定义。
如果我将该值设置为Mapper级别,它将应用于所有方法,包括创建和更新。
@Mapper // If I define null strategy here, it will be applied to all methods
public interface AmcPkgMapper {
AmcPkgMapper MAPPER = Mappers.getMapper(AmcPkgMapper.class);
AmcPackage create(AmcPackageRequest amcPackageRequest);
// How to define the null strategy here??
void update(AmcPackageRequest amcPackageRequest, @MappingTarget AmcPackage amcPackage);
}
Run Code Online (Sandbox Code Playgroud)
并且,如果我使用将该方法设置为方法Mapping,则它希望我定义一个target对象,为此,我可能需要一个包装对象,并以某种方式映射其中的所有内部属性。
@Mapping(target = "amcPackage", nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
void update(AmcPackageRequest amcPackageRequest, @MappingTarget AmcPackageWrapper amcPackageWrapper);
Run Code Online (Sandbox Code Playgroud)
使用上述方法,生成的代码如下所示,该代码无需amcPackage …
我目前正在映射具有两个“子 DTOS”的 DTO。
例如。
PersonDTO有"firstName", "lastName", "languageDTO","zipCodeDTO"
现在在我的 PersonMapper 中,我想使用 my"LanguageMapper"和 my "ZipCodeMapper".
但是@Mapper(uses = "")我只能调用一个外部映射器在我的课堂上使用。
预先感谢您的帮助
这是我的 DTO 的代码
这是我的 ZipCodeDTO:
class ZipCodeDTO {
public static final String FIELD_SEPARATOR = "__";
private String favouriteZipCode;
private String cityName;
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFavouriteZipCode() {
return favouriteZipCode;
}
public void setFavouriteZipCode(String favouriteZipCode) { …Run Code Online (Sandbox Code Playgroud) 我有一个要映射的 UserDTO 和 User 实体。创建新用户时,某些字段(例如:password,modifiedBy)必须通过某种自定义方法生成(例如:password随机生成和编码,但modifiedBy用户名是从安全服务中检索的)。为此,我将一些服务自动连接到映射器中。他们中的许多人返回,String而 MapStruct 无法理解在每种情况下使用哪个,而只使用它在接受String作为输入的所有内容上找到的第一个。
@Mapper(componentModel = "spring", uses = PasswordEncoder.class)
public interface UserMapper {
@Mapping(target = "password", qualifiedByName = "PASS")
User mapUser(UserDto dto);
@Named("PASS")
default String getPass(PasswordEncoder passwordEncoder){
return passwordEncoder.encode(some_random_generator);
}
}
Run Code Online (Sandbox Code Playgroud)
这将生成仅使用PasswordEncoder任何接受的 setter 中的方法的代码,String并且getPass(...)根本不使用方法。但是我只需要它getPass(...)在password现场使用我的方法。