防止在更新时在Mapstruct中进行空检查

时间:2019-01-04 10:42:29

标签: 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;
}

我发送给UI的是UserDTO:

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);

}

userToUserDTO()可以正常工作,但是为我生成的userDTOToUser()似乎很奇怪:

@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;
}

有问题的用例:

  1. 在“用户”的所有字段中填写。
  2. 再次打开表单并清除电话字段。
  3. 这意味着要后端,我将发送如下内容:

userDTO: {
        name: 'John Doe';
        contactDataDTO: {
            email: 'johndoe@gmail.com',
            phone: null,
            address: 'Home'
        }
    }

因此,就我在生成的代码中对null进行检查而言,user.phone将不会更新。


我认为NullValueCheckStrategy是我所需要的,但是没有适合我的选择。 现在,我看到的唯一选择是-编写我自己的userDTOToUser()实现,不执行null检查。 也许您可以建议更好的解决方案,因为对我来说,对于任何使用非原始源DTO进行目标更新的映射器来说,这似乎都是一个问题。

可运行的演示:https://repl.it/@aksankin/SlateblueUnimportantStack

非常感谢。

3 个答案:

答案 0 :(得分:0)

可能是可选的<>是您要搜索的内容。在这种情况下,对于空字段,您将为null;如果从UI发送了null,则为null;对于实际值,则为Optional。但是可能您需要为请求和响应创建不同的DTO。

答案 1 :(得分:0)

如果您希望null为您提供一定的价值,那么您正在寻找source presence checking。然后,您可以在DTO的setPhone中控制是否设置了它,并添加将使用该标志的hasPhone。然后,MapStruct在设置值时将使用状态检查方法。

答案 2 :(得分:0)

尝试:

@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是一种类型,严格不需要)。