Hibernate check deletion constraints

泪湿孤枕 提交于 2019-12-06 15:28:05

One (not so simple) approach is to scan your entity class for @OneToMany or @ManyToMany annotated fields and perform checking so neat error message can be provided to user. Following sample code assumes you only annotate the field, not the getters method, eg:

public class Person {
  @OneToMany(..)
  private List<House> houses;
  //...
}

First get the list of all fields using reflection:

Fields[] fields = Person.class.getDeclaredFields();

Then iterate and check for @OneToMany or @ManyToMany annotations

for(Field f : fields) {
   if( f.getAnnotation(OneToMany.class) != null || 
       f.getAnnotation(ManyToMany.class) != null) {
     // Here you know f has to be checked before the person is deleted ...
   }
}

The value of a field of a particular person object can be obtained using:

Person p = // fetch a person ..
Field f = // assume f is the "List<House> houses" field
List<House> houses = (List<House>) f.get(p);

I had a similar problem, I had to check if an entity could be safely deleted to avoid foreign key constraint violations. This is how I solved:

First, I created an annotation to mark the entity that needs to be checked before deletion:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = SafeDeleteValidator.class)
public @interface SafeDelete {
  String message() default "{lima.jefferson.SafeDelete.message}";
  Class<?>[] groups() default { };
  Class<? extends Payload>[] payload() default { };
}

Then I created another annotation to be applied to any method that will be used to check if the entity can be deleted:

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CheckForDelete {
}

In the entity class I used these annotations like this:

@SafeDelete(message = "Couldn't delete this entity due to...")
public class MyEntity {

    @CheckForDelete
    public Boolean checkForDelete() {
        // Insert your business logic here
        return true;
    }

}

And finally, the validator for the SafeDelete annotation:

public class SafeDeleteValidator implements ConstraintValidator<SafeDelete, Object> {

  @Override
  public void initialize(SafeDelete constraintAnnotation) {

  }

  @Override
  public boolean isValid(Object object, ConstraintValidatorContext context) {

    Method[] methods = object.getClass().getMethods();

    return Arrays.stream(methods)
          .filter(m -> m.getAnnotation(CheckForDelete.class) != null)
          // Deal with the exception here 
          .map(m -> (Boolean) m.invoke(object))
          .reduce(true, (a, b) -> a && b);
  }

}

Then you can follow the answer of this question to apply the validation to deletion only.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!