![](/img/trans.png)
[英]Custom @Unique validator in Spring throws Hibernate Assertion failure
[英]Spring: Unique Id validator without using Hibernate
当您进行 POST 时,验证器检查没有重复 ID 的最佳方法是什么?
我试图创建一个自定义验证器,但总是出现Internal Server Error
{ "timestamp": "2020-04-25T14:37:19.158+0000", "status": 500, "error": "Internal Server Error", "message": "HV000030: No validator can be found for constraint ' com.omega.mtest.validator.IdConstraint'验证类型'java.lang.Integer'。检查'id'的配置”,“路径”:“/用户”}
这是我的 model class
public class User {
@IdConstraint
@Min(value = 1, message = "ID can't be zero or null")
@Max(value = 1000000, message = "We collect a billion records")
private int id;
@Pattern(regexp = "^[a-zA-Z ]*$", message = "Input doesn't match for a full name")
private String name;
@Min(value = 10)
@Max(value = 120, message = "We didn't expect that age")
private int age;
@Pattern(regexp = "^[a-zA-Z ]*$", message = "Input doesn't match for a city name")
private String city;
public User(int id, String name, int age, String city) {
this.id = id;
this.name = name;
this.age = age;
this.city = city;
}
//getters
}
自定义验证器接口:
@Constraint(validatedBy = UserValidator.class)
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RUNTIME)
public @interface IdConstraint {
String message() default "The input list cannot contain two ugual IDs";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Class实现接口
public class UserValidator implements ConstraintValidator<IdConstraint, List<User>> {
@Override
public void initialize(IdConstraint constraintAnnotation) {
}
@Override
public boolean isValid(List<User> users, ConstraintValidatorContext context) {
if (users.size() == 1) {
return true;
} else {
for (int i = 0; i < users.size(); i++) {
for (int j = 0; j < users.size(); j++) {
if (i != j) {
if (users.get(i).getId() == users.get(j).getId()) {
return true;
}
}
}
}
return false;
}
}
Controller class:
@Validated
@RestController
public class UsersController {
@Autowired
public UserService userService;
@RequestMapping(value = "/user", method = RequestMethod.POST)
public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
return new ResponseEntity<>(userService.createUser(user), HttpStatus.CREATED);
}
@ExceptionHandler(ConstraintViolationException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
ResponseEntity<String> handleConstraintViolationException(ConstraintViolationException e) {
return new ResponseEntity<>("Not valid due to validation error: " + e.getMessage(), HttpStatus.BAD_REQUEST);
}
@RequestMapping(value = "/users", method = RequestMethod.GET)
public List<User> getUsers() {
return userService.getAllUsers();
}
@RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
public User getUserById(@PathVariable int id) {
return userService.findUserById(id);
}
}
用户服务
public interface UserService {
List<User> getAllUsers();
User createUser(User user);
User findUserById(int id);
List<User> list();
}
回购
@Component
public class UserRepository implements UserService {
private List<User> users;
public UserRepository() {
users = new ArrayList<>();
}
@Override
public List<User> getAllUsers() {
return users.stream().collect(Collectors.toList());
}
@Override
public User createUser(User user) {
users.add(user);
return user;
}
@Override
public User findUserById(int id) {
return users.stream()
.filter(t -> t.getId() == id)
.findAny()
.orElse(null);
}
@Override
public List<User> list() {
return users;
}
}
您的验证人签名不正确。
您不是在这里验证用户列表,而是验证 Integer。
像这样
public class UserIdValidator implements ConstraintValidator<IdConstraint, Integer> {
然后,您必须询问您的服务是否已使用该 ID。
public class UserIdValidator implements ConstraintValidator<IdConstraint, Integer> {
@Autowired
Private UserService userService;
@Override
public void initialize(IdConstraint constraintAnnotation) {
}
@Override
public boolean isValid(Integer id, ConstraintValidatorContext context) {
return !userService.existsById(id);
}
}
首先,您在错误的地方使用@IdConstraint
意味着private int id
。 你必须把它放在List<User>
上。 当您有用户列表并且两个用户中的任何一个在请求正文中没有相同的 id 时,您的验证器就会工作。 你可以解决这两种方式。
检查是服务:
在 post 端点中,您使用一个用户作为请求正文。 因此,您可以使用存储库的getById()
检查服务中的数据库中是否存在 id。 如果存在则引发异常,否则插入。
User user= userRepository.getById(user.getId());
if (ObjectUtils.isEmpty(user)) {
throw new UserNotFoundException();
}
使用验证器:
在验证器 function 中调用存储库并不是更好的方法。 但是,您仍然希望可以这样做。
public class UserIdValidator implements ConstraintValidator<IdConstraint, Integer> {
@Autowired
Private UserService userService;
@Override
public void initialize(IdConstraint constraintAnnotation) {
}
@Override
public boolean isValid(Integer id, ConstraintValidatorContext context) {
User user= userService.findUserById(id);
if (ObjectUtils.isEmpty(user)) {
return false;
}
return true;
}
}
我这样做了,它正在工作:
@RequestMapping(value = "/user", method = RequestMethod.POST)
public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
Optional<User> check = userService.findUserById(user.getId());
if (check.isPresent()) {
return new ResponseEntity<>(userService.createUser(user), HttpStatus.CREATED);
}
return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
}
@RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
public ResponseEntity<User> getUserById(@PathVariable int id) {
if (userService.findUserById(id).isPresent()) {
return new ResponseEntity<>(userService.findUserById(id).get(), HttpStatus.OK);
}
return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.