1

我正在使用 Spring - Hibernate 来控制我的应用程序中的模型。这些模型相互链接(一对多,多对多,几乎是各种关系),现在我在删除一个被其他实体使用的实体时遇到了问题。问题是我想显示详细消息,该消息准确地告知其他对象(类型、名称)正在使用我要删除的实体。这不是 Hibernate 向我抛出的关于违反约束的常见信息。
例如:Car --> Person, House --> Person; 然后,当我删除一个拥有汽车和房屋的人时,消息将显示“有汽车(名为福特野马)和房屋(名为 MyHouse)与此人相关联”。
1. 那么Hibernate有什么方法支持这个要求吗?我想这个特定要求没有实现。
2.如果没有任何实用程序可用于此问题,我正在考虑以下解决方案:
- 在每个实体类(即Person)中,我将定义检测从该实体到其他实体的链接的所有检查方法,例如:

class Person {
     // Properties
     // Checking methods, return type and name of linked objects
     public Map<String, String> getLinkedCars() {
         // Query to DB to get linked cars
         // return a Map contain Class name along with object name <Car, Ford Mustang>
     }

     public Map<String, String> getLinkedHouses() {
         // Query to DB to get linked houses
         // return a Map contain Class name along with object name <House, MyHouse>
     }
}

-然后,在删除Person实体之前的服务中,我将使用反射机制收集检查方法(名称以“getLinkedXXX”开头)的结果,并构建详细的错误消息。
那么这个解决方案好吗?关于 MVC 的性能和约定(因为我必须在模型类中查询数据)?
谢谢您的帮助。

4

2 回答 2

1

一种(不是那么简单)的方法是扫描您的实体类@OneToMany@ManyToMany带注释的字段并执行检查,以便可以向用户提供简洁的错误消息。以下示例代码假定您只注释字段,而不是 getters 方法,例如:

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

首先使用反射获取所有字段的列表:

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

然后迭代并检查@OneToMany@ManyToMany注释

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 ...
   }
}

可以使用以下方法获得特定人员对象的字段值:

Person p = // fetch a person ..
Field f = // assume f is the "List<House> houses" field
List<House> houses = (List<House>) f.get(p);
于 2013-07-01T07:24:45.093 回答
0

我遇到了类似的问题,我必须检查是否可以安全地删除实体以避免违反外键约束。我就是这样解决的:

首先,我创建了一个注解来标记删除前需要检查的实体:

@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 { };
}

然后我创建了另一个注释以应用于将用于检查实体是否可以删除的任何方法:

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

在实体类中,我使用了这些注释,如下所示:

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

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

}

最后,SafeDelete注释的验证器:

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);
  }

}

然后,您可以按照此问题的答案将验证仅应用于删除。

于 2018-12-04T20:37:00.820 回答