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

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

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 &quot;Invalid TestA.&quot;;
    	Class&lt;?&gt;[] groups() default {};
		Class&lt;? extends Payload&gt;[] payload() default {};
}

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

public class GroupConstraintValidator implements ConstraintValidator&lt;GroupConstraint, Group&gt;{

	@Override
	public boolean isValid(Group object, ConstraintValidatorContext context) {
		 if (!(object instanceof Group)) {
	            throw new IllegalArgumentException(&quot;@CustomConstraint only applies to TestA&quot;);
	        }
		 Group group = (Group) object;
		 if (group.getParent() != null &amp;&amp; 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= &quot;ID&quot;,unique = true)
	private Long id;

	private String name;

	@JoinColumn(name = &quot;IDPARENT&quot;, nullable = true, referencedColumnName = &quot;ID&quot;)
	@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);

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:

确定