如何向需要查询实体以执行验证的 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());
    }
}