如何向需要查询实体以执行验证的 JPA 实体添加验证
how to add validation to JPA Entities where it requires to query the entity to perform validation
假设我有以下实体:
@Entity
public class MyModel {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private Integer counter;
private Integer someVal;
}
我想在这个实体上进行 CRUD 操作和一些额外的方法,
因此我有一个存储库,例如
@Repository
public interface MyModelRepository extends JpaRepository<MyModel, Long> {}
问题:
我想在保存时添加某些验证,我需要在其中查询模型。
例如:在保存时,检查 someVal 的值是否大于 MyModel 的 someVal,其计数器比当前保存的对象小 1。
PS:也可能是跨实体验证。
PS: 还需要用到JpaRepository自动生成的crud
否则,我必须实现 DAO 并编写自定义实现,然后将其映射到 RestController。
我最理想的是在保留其余部分的同时自定义某些部分。
如果有人想知道我是如何解决的:
方法一:原始方式
@RestController
public class MyModelController {
// autowired MyModelRepository & other models repositories
@RequestMapping(method = {RequestMethod.POST, RequestMethod.PUT})
public long save(MyModel model){
// added validation here (which involves queries to both repositories
// returned saved entity.id or failed with 0
}
}
方法二:
显然,问题是关于更好的方法。
正如@Alan Hay 建议使用 Validator
,但仍然使用 Controller。文档不清楚如何在没有控制器覆盖的情况下将 Validator
绑定到 Repository
。
public class MyModelValidator implements Validator{
// Autowired MyModel repository and others
// override both supports() and validate()
// PS: moved validation logic from Controller in method 1 to validate()
}
现在将控制器更改为:
@RestController
public class MyModelController {
// autowired MyModelRepository & other models repositories
// autowire MyModelValidator as mymodelValidator
@RequestMapping(method = {RequestMethod.POST, RequestMethod.PUT})
public long save(@ModelAttribute("myModel") MyModel model, BindingResult result){
mymodelValidator.validate(model, result);
if(result.hasErrors()){
// return 0
}
// save & return saved entity's id
}
}
方法三:最后是怎么做的。
@SpringBootApplication
public class MyApplication extends RepositoryRestConfigurerAdapter{
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
@Override
public void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener) {
validatingListener.addValidator("beforeCreate", new MyModelValidator());
validatingListener.addValidator("beforeSave", new MyModelValidator());
}
}
假设我有以下实体:
@Entity
public class MyModel {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private Integer counter;
private Integer someVal;
}
我想在这个实体上进行 CRUD 操作和一些额外的方法, 因此我有一个存储库,例如
@Repository
public interface MyModelRepository extends JpaRepository<MyModel, Long> {}
问题: 我想在保存时添加某些验证,我需要在其中查询模型。
例如:在保存时,检查 someVal 的值是否大于 MyModel 的 someVal,其计数器比当前保存的对象小 1。
PS:也可能是跨实体验证。 PS: 还需要用到JpaRepository自动生成的crud
否则,我必须实现 DAO 并编写自定义实现,然后将其映射到 RestController。
我最理想的是在保留其余部分的同时自定义某些部分。
如果有人想知道我是如何解决的:
方法一:原始方式
@RestController
public class MyModelController {
// autowired MyModelRepository & other models repositories
@RequestMapping(method = {RequestMethod.POST, RequestMethod.PUT})
public long save(MyModel model){
// added validation here (which involves queries to both repositories
// returned saved entity.id or failed with 0
}
}
方法二:
显然,问题是关于更好的方法。
正如@Alan Hay 建议使用 Validator
,但仍然使用 Controller。文档不清楚如何在没有控制器覆盖的情况下将 Validator
绑定到 Repository
。
public class MyModelValidator implements Validator{
// Autowired MyModel repository and others
// override both supports() and validate()
// PS: moved validation logic from Controller in method 1 to validate()
}
现在将控制器更改为:
@RestController
public class MyModelController {
// autowired MyModelRepository & other models repositories
// autowire MyModelValidator as mymodelValidator
@RequestMapping(method = {RequestMethod.POST, RequestMethod.PUT})
public long save(@ModelAttribute("myModel") MyModel model, BindingResult result){
mymodelValidator.validate(model, result);
if(result.hasErrors()){
// return 0
}
// save & return saved entity's id
}
}
方法三:最后是怎么做的。
@SpringBootApplication
public class MyApplication extends RepositoryRestConfigurerAdapter{
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
@Override
public void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener) {
validatingListener.addValidator("beforeCreate", new MyModelValidator());
validatingListener.addValidator("beforeSave", new MyModelValidator());
}
}