Java 在更新时防止Mapstruct中的空检查
我正在努力进行表单更新。请考虑这个例子:Java 在更新时防止Mapstruct中的空检查,java,mapstruct,Java,Mapstruct,我正在努力进行表单更新。请考虑这个例子: // Entity with which I need to perform CRUD operations public class User { private String name; private String email; private String phone; private String address; } 我发送到用户界面的目的是: public class UserDTO { priva
// Entity with which I need to perform CRUD operations
public class User {
private String name;
private String email;
private String phone;
private String address;
}
我发送到用户界面的目的是:
public class UserDTO {
private String name;
private ContactDataDTO contactDataDTO;
}
public class ContactDataDTO {
private String email;
private String phone;
private String address;
}
我的地图绘制者:
@Mapper
public interface UserMapper {
@Mappings({
@Mapping(source="email", target="contactDataDTO.email"),
@Mapping(source="phone", target="contactDataDTO.phone"),
@Mapping(source="address", target="contactDataDTO.address")
})
UserDTO userToUserDTO(User user);
@InheritInverseConfiguration
User updateUserFromUserDTO(UserDTO userDTO, @MappingTarget User user);
}
UserToUserToUserTo()按预期工作,但为我生成的UserdToUserToUser()似乎很有趣:
@Override
public User updateUserFromUserDTO(UserDTO userDTO, User user) {
if ( userDTO == null ) {
return null;
}
String address = userDTOContactDataDTOAddress( userDTO );
if ( address != null ) {
user.setAddress( address );
}
String phone = userDTOContactDataDTOPhone( userDTO );
if ( phone != null ) {
user.setPhone( phone );
}
String email = userDTOContactDataDTOEmail( userDTO );
if ( email != null ) {
user.setEmail( email );
}
user.setName( userDTO.getName() );
return user;
}
有问题的用例:
所以,只要我在生成的代码中对user.phone进行空检查,它就不会被更新
我认为我需要的是NullValueCheckStrategy,但没有适合我的选项。 目前,我看到的唯一选项是编写自己的userDTOToUser()实现,而不进行空检查。 也许你们可以建议更好的解决方案,因为对我来说,对于从DTO到非原始源的目标更新,在任何映射程序中都可能出现问题 可运行演示:
非常感谢。您正在搜索的可能是可选的。在这种情况下,空字段为null,从UI发送null时为可选,实际值为可选。但是您可能需要为请求和响应创建不同的DTO。如果希望
null
为您提供特定的值,那么您正在寻找。然后,您可以在DTO的setPhone
中控制它是否已设置,并添加将使用该标志的hasPhone
。然后,MapStruct将在设置值时使用状态检查方法。尝试:
@Mapper( )
public interface UserMapper {
UserMapper INSTANCE = Mappers.getMapper( UserMapper.class );
@Mappings({
@Mapping(source="email", target="contactDataDTO.email"),
@Mapping(source="phone", target="contactDataDTO.phone"),
@Mapping(source="address", target="contactDataDTO.address")
})
UserDTO userToUserDTO(User user);
default void updateUserFromUserDTO(UserDTO userDTO, User user) {
intUpdateUserFromUserDTO( userDTO, userDTO.getContactDataDTO(), user );
}
void intUpdateUserFromUserDTO(UserDTO userDTO, ContactDataDTO contactDataDTO, @MappingTarget User user);
}
(注意:我返回了void iso a类型,这是绝对不需要的)。我见过的最漂亮的代码样式之一。在MapStruct 1.3Beta2中,我们引入了
NullValuePropertyMappingStrategy
专门用于控制更新方法。在我看来,这不适用于嵌套属性。我需要进一步调查。@sjaak试过了,没有帮助。基本上尝试了所有注释和所有选项(无论如何连接到“null”),我现在能想到的最干净的解决方法是从UserDTO创建新的用户对象,然后用UserDTO.id更新User.id。但如果可能的话,我很乐意知道推荐的方法。我也尝试过(你是对的)。请在MapStruct()上写一个问题。。我已经开始看了:)。同时,在这个场景中不要使用目标嵌套(这是在还原源嵌套时发生的情况)。我将提供一个变通方法作为答案。@OksanaMykhalets':作为加力燃烧室:它将与您当前的示例一起开箱即用(我使用了您的示例来实现这一点,谢谢)。1.3将很快发布。感谢您的回复。我试图添加hasPhone()方法,但它仍然不适合我。我能请你检查一下这个可运行的演示吗,也许你会发现一个错误?好的,这是我们在最新版本中添加的内容。能否尝试将hasContactDataDTO
添加到UserDTO
?这应该会产生一些你正在寻找的东西。我可以在以后相应地更新答案。另一个选择是从联系人处更新用户。您不需要使用嵌套源代码
@Mapper( )
public interface UserMapper {
UserMapper INSTANCE = Mappers.getMapper( UserMapper.class );
@Mappings({
@Mapping(source="email", target="contactDataDTO.email"),
@Mapping(source="phone", target="contactDataDTO.phone"),
@Mapping(source="address", target="contactDataDTO.address")
})
UserDTO userToUserDTO(User user);
default void updateUserFromUserDTO(UserDTO userDTO, User user) {
intUpdateUserFromUserDTO( userDTO, userDTO.getContactDataDTO(), user );
}
void intUpdateUserFromUserDTO(UserDTO userDTO, ContactDataDTO contactDataDTO, @MappingTarget User user);
}