Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/341.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何将Dto修补到实体?_Java_Spring_Spring Boot_Jpa_Dto - Fatal编程技术网

Java 如何将Dto修补到实体?

Java 如何将Dto修补到实体?,java,spring,spring-boot,jpa,dto,Java,Spring,Spring Boot,Jpa,Dto,我有一个接受dto对象的控制器。我需要更改dto对象中存在的字段 @PatchMapping(value = "/update/{uuid}") public ResponseEntity<UserDto> update( @RequestBody UserDto userDto, @PathVariable("uuid")UUID uuid) throws UserNotFoundException {

我有一个接受dto对象的控制器。我需要更改dto对象中存在的字段

@PatchMapping(value = "/update/{uuid}")
    public ResponseEntity<UserDto> update(
            @RequestBody UserDto userDto,
            @PathVariable("uuid")UUID uuid) throws UserNotFoundException {           
        User updatedUser = userService.update(
                userMapper.userDtoToUser(userDto),
                uuid
        );           
        return .....
    }
@PatchMapping(value=“/update/{uuid}”)
公众回应更新(
@RequestBody UserDto UserDto,
@PathVariable(“uuid”)uuid uuid)引发UserNotFoundException{
User updateuser=userService.update(
userMapper.userDtoToUser(userDto),
uuid
);           
返回。。。。。
}

但是userService只能接受实体。我需要使用映射器dto->实体。但是实体不能有dto中的空字段(假设您只需要更改一个字段)。在这种情况下该怎么办?我知道控制器不应该包含逻辑

您可以使用反射来检查空属性和复制的Beanutil

User updatedUser = new User();
BeanUtils.copyProperties(userDto, updatedUser, getNullPropertyNames(userDto));
在春天,这将是我检查空属性的方式

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

    Set<String> emptyNames = new HashSet<>();
    for(PropertyDescriptor pd : pds) {
        Object srcValue = src.getPropertyValue(pd.getName());
        if (srcValue == null) emptyNames.add(pd.getName());
    }
    return emptyNames.toArray(new String[0]);
}

解决此问题的两种可能方法。您必须更改服务方法以接受dto而不是实体,或者必须创建一个
@组件
类,该类实现、重写转换方法并在那里执行必要的字段更改,然后在控制器中调用
@Autowire
,并调用
genericConversionService.convert(userDto,User.class)

转换器应如下所示:

import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

@Component
public class UserDtoToUser implements Converter<UserDto, User> {

    @Override
    public User convert(UserDto source) {
        User user = new User();
        // user.set ..... for all necessary fields
        return user;
    }

}

当然,将字段更改为dto中的任何内容。此外,如果您需要进行更多验证,还可以添加许多其他验证注释。

正如您所说,控制器不应包含逻辑,因此,对于这个Spring有一个接口,该接口是
Validator

将验证视为业务逻辑有其利弊,Spring提供了一种验证(和数据绑定)设计,不排除其中任何一种。具体来说,验证不应该绑定到web层,应该易于本地化,并且应该可以插入任何可用的验证器。综上所述,Spring提供了一个验证器接口,它在应用程序的每一层都是基本的,而且非常可用

这是您需要做的:

Spring提供了一个验证器接口,您可以使用它来验证对象。Validator接口使用Errors对象工作,因此在验证时,验证器可以向Errors对象报告验证失败

我们有一个DTO,我们将对其验证字段:

public class Person {
    private String name;
    private int age;

    // the usual getters and setters...
}
要进行验证,我们必须实现验证程序接口:

    public class PersonValidator implements Validator {

    /**
     * This Validator validates *just* Person instances
     */
    public boolean supports(Class clazz) {
        return Person.class.equals(clazz);
    }

    public void validate(Object obj, Errors e) {
        if (supports(obj.getClass())) {
            ValidationUtils.rejectIfEmpty(e, "name", "name.empty");
            Person p = (Person) obj;
            if (p.getAge() < 0) {
                e.rejectValue("age", "negativevalue");
            } else if (p.getAge() > 110) {
                e.rejectValue("age", "too.darn.old");
            }
        }
    }
}
公共类PersonValidator实现验证器{
/**
*此验证器验证*仅*个人实例
*/
公共布尔支持(类clazz){
返回人.class.equals(clazz);
}
公共无效验证(对象obj,错误e){
if(支持(obj.getClass()){
ValidationUtils.rejectIfEmpty(e,“name”,“name.empty”);
人员p=(人员)obj;
if(p.getAge()<0){
e、 拒绝价值(“年龄”、“负面价值”);
}else if(p.getAge()>110){
e、 拒绝价值(“年龄”、“太老了”);
}
}
}
}
如果DTO通过了所有验证,则可以将DTO映射到实体对象


您可以在此处找到更多信息

您是否考虑过将userService更改为userDto而不是userEntity?服务层应该是处理转换逻辑的层,对吗?在实体类中添加一个构造函数,该构造函数接受DTO对象作为唯一参数。您的问题是转换还是验证DTO字段?在Spring MVC中,修补/prtial更新并不容易。这里有一些讨论:。这里可能的方法是:这是非常过时的。现在,您可以使用
@NotBlank
@Min
直接注释字段本身,只需在UserDto UserDto request body参数前面添加
@Valid
,Pikachu可以验证字段是否为空,我认为这是他所要求的,通过这种方式,您可以管理这种情况,并拥有更多的控制权。这种映射如何处理DTO中的空值?它怎么知道它们是(a)在请求中不存在还是(b)在请求中存在但显式为空?我最初认为问题是关于用户实体中的字段,这些字段在dto中不存在,但是强制性的,但由于您不是第一个对此提出问题的人,OP仍然没有回复我发布的评论,我将编辑此答案以包括dto验证。
    public class PersonValidator implements Validator {

    /**
     * This Validator validates *just* Person instances
     */
    public boolean supports(Class clazz) {
        return Person.class.equals(clazz);
    }

    public void validate(Object obj, Errors e) {
        if (supports(obj.getClass())) {
            ValidationUtils.rejectIfEmpty(e, "name", "name.empty");
            Person p = (Person) obj;
            if (p.getAge() < 0) {
                e.rejectValue("age", "negativevalue");
            } else if (p.getAge() > 110) {
                e.rejectValue("age", "too.darn.old");
            }
        }
    }
}