JPA实体:如何检查递归父项

huangapple go评论97阅读模式
英文:

JPA Entities: how to check recursive parents

问题

我有一个简单的实体表示一个群组。

  1. public class Group {
  2. Long id;
  3. String name;
  4. @JoinColumn(name = "idparent", nullable = true, referencedColumnName = "ID")
  5. @ManyToOne(targetEntity = Group.class, fetch = FetchType.EAGER, cascade = {}, optional = true)
  6. private Group parent;
  7. }

一个群组可以是一些群组的父群组。

在测试期间,我设置 A.parent = A,所以对象 A 陷入了递归。

是否有一个注解或者什么东西可以检查以下约束?

  1. a.id != a.parent.id
英文:

I have a simple entity representing a group.

  1. public class Group {
  2. Long id;
  3. String name;
  4. @JoinColumn(name = "idparent", nullable = true, referencedColumnName = "ID")
  5. @ManyToOne(targetEntity = Group.class, fetch = FetchType.EAGER, cascade = {}, optional = true)
  6. private Group parent;
  7. }

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?

  1. a.id != a.parent.id

答案1

得分: 1

您可以创建一个自定义验证器和类级别的注解约束,使用验证 API 的 Constraint 注解绑定一个验证器类。

  1. @Constraint(validatedBy = GroupConstraintValidator.class)
  2. @Target({TYPE })
  3. @Retention(RUNTIME)
  4. public @interface GroupConstraint {
  5. String message() default "Invalid TestA.";
  6. Class<?>[] groups() default {};
  7. Class<? extends Payload>[] payload() default {};
  8. }

创建一个验证器类,其中包含验证逻辑以检查 a.id != a.parent.id

  1. public class GroupConstraintValidator implements ConstraintValidator<GroupConstraint, Group>{
  2. @Override
  3. public boolean isValid(Group object, ConstraintValidatorContext context) {
  4. if (!(object instanceof Group)) {
  5. throw new IllegalArgumentException("@CustomConstraint only applies to TestA");
  6. }
  7. Group group = (Group) object;
  8. if (group.getParent() != null && group.getParent().getId() == group.getId()) {
  9. return false;
  10. }
  11. return true;
  12. }
  13. }

将此约束应用于实体类 Group

  1. @Entity
  2. @GroupConstraint
  3. public class Group {
  4. @Id
  5. @GeneratedValue(strategy = GenerationType.AUTO)
  6. @Column(name= "ID", unique = true)
  7. private Long id;
  8. private String name;
  9. @JoinColumn(name = "IDPARENT", nullable = true, referencedColumnName = "ID")
  10. @ManyToOne(targetEntity = Group.class, fetch = FetchType.EAGER, cascade = {}, optional = true)
  11. private Group parent;
  12. }

现在,在生命周期回调期间,即当子引用自身时,验证提供程序应该抛出约束违规。

  1. Group child = new Group();
  2. // 设置属性
  3. child.setParent(child);
  4. 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.

  1. @Constraint(validatedBy = GroupConstraintValidator.class)
  2. @Target({TYPE })
  3. @Retention(RUNTIME)
  4. public @interface GroupConstraint {
  5. String message() default &quot;Invalid TestA.&quot;;
  6. Class&lt;?&gt;[] groups() default {};
  7. Class&lt;? extends Payload&gt;[] payload() default {};
  8. }

Create the validator class with the validation logic to check a.id != a.parent.id

  1. public class GroupConstraintValidator implements ConstraintValidator&lt;GroupConstraint, Group&gt;{
  2. @Override
  3. public boolean isValid(Group object, ConstraintValidatorContext context) {
  4. if (!(object instanceof Group)) {
  5. throw new IllegalArgumentException(&quot;@CustomConstraint only applies to TestA&quot;);
  6. }
  7. Group group = (Group) object;
  8. if (group.getParent() != null &amp;&amp; group.getParent().getId() == group.getId()) {
  9. return false;
  10. }
  11. return true;
  12. }
  13. }

Apply this constraint to the entity class, Group.

  1. @Entity
  2. @GroupConstraint
  3. public class Group {
  4. @Id
  5. @GeneratedValue(strategy = GenerationType.AUTO)
  6. @Column(name= &quot;ID&quot;,unique = true)
  7. private Long id;
  8. private String name;
  9. @JoinColumn(name = &quot;IDPARENT&quot;, nullable = true, referencedColumnName = &quot;ID&quot;)
  10. @ManyToOne(targetEntity = Group.class, fetch = FetchType.EAGER, cascade = {}, optional = true)
  11. private Group parent;

Now the validation provider should through a constraint violation during lifecycle callbacks , that is when child references itself.

  1. Group child = new Group();
  2. //set attributes
  3. child.setParent(child);
  4. em.persist(child);

huangapple
  • 本文由 发表于 2020年9月18日 00:50:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/63942743.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定