英文:
JPA Entities: how to check recursive parents
问题
我有一个简单的实体表示一个群组。
public class Group {
Long id;
String name;
@JoinColumn(name = "idparent", nullable = true, referencedColumnName = "ID")
@ManyToOne(targetEntity = Group.class, fetch = FetchType.EAGER, cascade = {}, optional = true)
private Group parent;
}
一个群组可以是一些群组的父群组。
在测试期间,我设置 A.parent = A
,所以对象 A 陷入了递归。
是否有一个注解或者什么东西可以检查以下约束?
a.id != a.parent.id
英文:
I have a simple entity representing a group.
public class Group {
Long id;
String name;
@JoinColumn(name = "idparent", nullable = true, referencedColumnName = "ID")
@ManyToOne(targetEntity = Group.class, fetch = FetchType.EAGER, cascade = {}, optional = true)
private Group parent;
}
A group can be the parent of some groups.
During tests I set A.parent = A
, so the A object fall in recursion.
Is there an annotation or something to check the following constraint?
a.id != a.parent.id
答案1
得分: 1
您可以创建一个自定义验证器和类级别的注解约束,使用验证 API 的 Constraint 注解绑定一个验证器类。
@Constraint(validatedBy = GroupConstraintValidator.class)
@Target({TYPE })
@Retention(RUNTIME)
public @interface GroupConstraint {
String message() default "Invalid TestA.";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
创建一个验证器类,其中包含验证逻辑以检查 a.id != a.parent.id
:
public class GroupConstraintValidator implements ConstraintValidator<GroupConstraint, Group>{
@Override
public boolean isValid(Group object, ConstraintValidatorContext context) {
if (!(object instanceof Group)) {
throw new IllegalArgumentException("@CustomConstraint only applies to TestA");
}
Group group = (Group) object;
if (group.getParent() != null && group.getParent().getId() == group.getId()) {
return false;
}
return true;
}
}
将此约束应用于实体类 Group
:
@Entity
@GroupConstraint
public class Group {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name= "ID", unique = true)
private Long id;
private String name;
@JoinColumn(name = "IDPARENT", nullable = true, referencedColumnName = "ID")
@ManyToOne(targetEntity = Group.class, fetch = FetchType.EAGER, cascade = {}, optional = true)
private Group parent;
}
现在,在生命周期回调期间,即当子引用自身时,验证提供程序应该抛出约束违规。
Group child = new Group();
// 设置属性
child.setParent(child);
em.persist(child);
英文:
You can create a custom validator and class level annotation constraint, bind a validator class using the Constraint annotation of validation api.
@Constraint(validatedBy = GroupConstraintValidator.class)
@Target({TYPE })
@Retention(RUNTIME)
public @interface GroupConstraint {
String message() default "Invalid TestA.";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Create the validator class with the validation logic to check a.id != a.parent.id
public class GroupConstraintValidator implements ConstraintValidator<GroupConstraint, Group>{
@Override
public boolean isValid(Group object, ConstraintValidatorContext context) {
if (!(object instanceof Group)) {
throw new IllegalArgumentException("@CustomConstraint only applies to TestA");
}
Group group = (Group) object;
if (group.getParent() != null && group.getParent().getId() == group.getId()) {
return false;
}
return true;
}
}
Apply this constraint to the entity class, Group.
@Entity
@GroupConstraint
public class Group {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name= "ID",unique = true)
private Long id;
private String name;
@JoinColumn(name = "IDPARENT", nullable = true, referencedColumnName = "ID")
@ManyToOne(targetEntity = Group.class, fetch = FetchType.EAGER, cascade = {}, optional = true)
private Group parent;
Now the validation provider should through a constraint violation during lifecycle callbacks , that is when child references itself.
Group child = new Group();
//set attributes
child.setParent(child);
em.persist(child);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论