我使用Spring - Hibernate来控制应用程序中的模型。模型彼此链接(一对多,多对多,几乎种类的关系),现在我在删除其他实体正在使用的实体时遇到问题。问题是我想显示详细消息,该消息准确地告知其他对象(类型,名称)正在使用我要删除的实体。 Hibernate抛出的不是关于约束违规的常见信息
例如:Car --> Person, House --> Person
;然后当我删除一个有车和房子的人时,该消息将显示“有车(名为Ford Mustang)和House(名为MyHouse)链接到此人”。
那么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的性能和惯例(因为我必须在模型类中查询数据)?
谢谢你的帮助。
答案 0 :(得分: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);
答案 1 :(得分: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);
}
}
然后,您可以按照此question的回答将验证仅应用于删除。