Java 如何将Dto修补到实体?
我有一个接受dto对象的控制器。我需要更改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 {
@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");
}
}
}
}