映射到dto时如何从Put请求中排除null值

时间:2019-03-13 15:30:34

标签: java spring spring-boot mapping dto

我使用RestController将数据更新到db,但是出现问题。当我更新值时,如果来自我的更新的值为null,则始终将数据更新到db为null。我不要我想要如果我的请求中具有值的1个字段为null,我不想更新它。

下面是我的代码:

控制器:

RestController

@RequestMapping("/api/products")
@Api(value = "ProductControllerApi",produces = MediaType.APPLICATION_JSON_VALUE)

public class ProductController {

    @Autowired
    private ProductService productService;

    @PatchMapping("/{id}")
    public ResponseEntity<ProductResDto> updateProduct(@RequestBody ProductReqDto productReqDto, @PathVariable String id) {
        return ResponseEntity.ok(productService.updateProduct(product,id));
    }

ProductReqDto:

     public class ProductReqDto {

    private String name;
    private String type;
    private String category;
    private String description;
    private Double prince;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Double getPrince() {
        return prince;
    }

    public void setPrince(Double prince) {
        this.prince = prince;
    }
}

ProductResDto:

   public class ProductResDto {

    private String name;
    private String type;
    private String category;
    private Double prince;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Double getPrince() {
        return prince;
    }

    public void setPrince(Double prince) {
        this.prince = prince;
    }
}

MappingDto:

private ProductDto convertToProductDto(ProductReq product) {
    return modelMapper.map(product, ProductResDto.class);
}

如何处理方法convertToProductD到仅映射值不为null的映射。因为if映射一个字段:example:product_name = null,它将插入到db null中。我想要字段ProductReq是否具有值,它映射并在数据库中保留其他不同的字段(如果不包含ProductReq的值,则不将其设置为null)。 示例:

**ReqProductDto.class**   
    private String name;
    private String type;
    private String category;
    private String description;
    private Double prince;

但如果用户仅更新两个字段:

   private String name;
    private String type;

我想要春季更新字段名称和字段 type 用户输入,并将类别,描述,王子保留在数据库中。在我的情况下,如果用户更新两个字段:名称和字段类型,spring将对其进行更新,但spring set category,description,prince 为空在我的数据库中。我不要 请帮助我,谢谢。

2 个答案:

答案 0 :(得分:0)

您已将其标记为spring-boot,所以我假设您可能正在使用控制器并验证其参数。如果是这样,只需

import javax.validation.constraints.NotNull;

public class ProductReqDto {

    @NotNull
    private String name;
    @NotNull
    private String type;
    @NotNull
    private String category;
    @NotNull
    private String description;
    @NotNull
    private Double prince;

    ...

}

并对这样的控制器使用@Valid

@PatchMapping("/{id}")
public ResponseEntity<ProductResDto> updateProduct(@RequestBody @Valid ProductReqDto productReqDto, @PathVariable String id) {
    return ResponseEntity.ok(productService.updateProduct(product,id));
}

然后将在实例化时验证您的对象。

答案 1 :(得分:0)

您想要的主要用于PATCH映射。 在PUT映射中,对象的所有字段都需要覆盖,但是在PATCH映射中,仅需要覆盖提供的字段,而无需更改其他字段。

所以, 对于现有记录,

employee{ employeeId = "A2RTD", empName = "satish", "country": "India"}

而且,现在有一个非强制性的野外移动电话需要与国家一起更新

DTO请求将包含ID以外的所有字段,但只有国家/地区和手机号码不会为空

在这种情况下,我们可以使用spring软件包中的BeanUtils

import org.springframework.beans.BeanUtils;
    public static Object getDtoMapping(Object source, Object destination) {
    BeanUtils.copyProperties(source, destination, getNullFieldNames(source));
    return destination;
}

    public static String[] getNullFieldNames(Object source) {
    final BeanWrapper src = new BeanWrapperImpl(source);
    PropertyDescriptor[] pds = src.getPropertyDescriptors();

    Set<String> fieldNames = new HashSet<>();
    for (PropertyDescriptor pd : pds) {
        Object srcValue = src.getPropertyValue(pd.getName());
        if (srcValue == null)
            fieldNames.add(pd.getName());
    }

    String[] result = new String[fieldNames.size()];
    return fieldNames.toArray(result);
}

此函数“ getNullFieldNames”将返回值为null的fieldNames。因此,根据BeanUtils中的第3个可选参数,不会映射这些字段

而且,您需要通过

// PATCH
EmployeeDao emp = findById(empCode);
emp = (EmployeeDao) getDtoMapping(empUpdateDto, emp);

在这里,在BeanUtil copyProperties中,第3个参数是可选的。如果提供,则适用于PATCH映射,如果不提供,则其行为与PUT映射相同。

因此,对于PUT映射,忽略null等同于不忽略。 您可以在POST,PUT映射中使用相同的内容。

// POST MAPPING
EmployeeDao emp = (EmployeeDao) getDtoMapping(empCreateDto, new Employee());