首页 > 解决方案 > 休眠方法验证并不总是有效

问题描述

为什么 Hibernate 的验证 - ConstraintViolationException - 没有在带有 spring-boot-starter-web 的 SpringBoot 应用程序(SpringBoot 的最新版本)的 main() 中抛出:

@Validated
@SpringBootApplication
public class Application {
public static void main(String[] args) {
   SpringApplication.run(Application.class, args);
   someService.doStuff(new Item(null);  // WHY NOT THROWN????????!!!!!! 
   // Expecting ConstraintViolationException: doStuff.item.content: must not be null
}}
// ----------------------

public class Item {
    @NotNull
    String content;  // to be validated
   //constructor, getter, setter
}

@Validated
@Service
public class SomeService {
    void doStuff(@Valid Item item) {} // should break for Item's content = null
}

奇怪的是,在其他情况下,Hibernate 验证对相同的方法调用按预期工作:

  1. 当我将无效调用放入控制器的构造函数时,会引发 ConstraintViolationException :
public SomeController(SomeService someService){
    this.someService = someService;
    someService.doStuff(new Item(null); // throws ConstraintViolationException  
}
  1. 同样如预期的那样,当我发出无效调用in a constructor method并在测试或 Postman 中调用端点时,会引发 ConstraintViolationException
@GetMapping("item")
public String item() {
    someService.doStuff(new Item(null); // throws ConstraintViolationException
    return "You never get here.";
}

标签: spring-boothibernatevalidationjavabeansconstraintviolationexception

解决方案


不知道你是如何获得someService实例的Application,但下面的代码对我有用(每个类都在不同的文件中):

@AllArgsConstructor
@Getter
@Setter
public class Item {

  @NotNull
  String content;
}



@Validated
@Service
public class SomeService {

  public void doStuff(@Valid Item item) {
    System.out.println(format("Item.content = %s", item.getContent()));
  }
}



@SpringBootApplication
public class TestingPurposeApplication {

  public static void main(String[] args) {
    ConfigurableApplicationContext context = SpringApplication.run(TestingPurposeApplication.class, args);
    SomeService someService = context.getBean(SomeService.class);
    someService.doStuff(new Item(null));
  }
}

结果:

ConstraintViolationException

利用:

ConfigurableApplicationContext context = SpringApplication.run(MyApplication.class, args);
MyClass myInstance = context.getBean(MyClass.class);

是在方法中获取由 Spring 管理的组件的合适main方法。


推荐阅读