【问题标题】:JPA: Custom constraint on @OneToMany fieldJPA:@OneToMany 字段上的自定义约束
【发布时间】:2013-05-23 08:50:33
【问题描述】:

我有以下场景:

@Entity public class Foo {
  @Id private Long id;

  @OneToMany(mappedBy = "foo")
  @MyCustomConstraint
  private Set<Bar> bars;
}

@Entity public class Bar {
  // ...

  @ManyToOne(optional = false)
  Foo foo;
}

我有自动生成的代码(即不能修改它)创建一个新的Bar 并通过调用bar.setFoo(foo) 将其添加到现有的FoosetFoo 确保 bar 也被添加到 foo 的集合中。然后自动生成的代码调用persist(bar)。此时我需要运行foo.bars 上的自定义约束验证器(新添加的bar 可能会违反它),但事实并非如此。

我的问题:

  1. 这是设计使然还是我做错了什么?
  2. 我该怎么做才能让它发挥作用?

编辑:

有关自定义约束的更多信息 - 尽管我认为这与问题并不特别相关。

这只是一个javax.validation 自定义约束:

@javax.annotation.Constraint(validatedBy = MyCustomConstraintValidator.class)
@AllTheOtherAnnotationStuff
public @interface MyCustomAnnotation {
}

public class MyCustomConstraintValidator implements ConstraintValidator<MyCustomConstraint, Set /*<Bar>*/ .class> {
  void initialize(MyCustomConstraint a) {}
  boolean isValid(Set /*<Bar>*/ s, ConstraintValidatorContext ctx) { ... }
}

如果我调用entityManager.persist(foo),则验证约束。如果我调用entityManager.persist(bar),它不是,即使该栏是新添加到其Foo 的集合中。

【问题讨论】:

  • 首先mappedBy 需要一个字段名(字符串)而不是一个类,这可能是一个错字。
  • 它是,已修复。这是部分从记忆中重现的问题。
  • 我不明白。您的自定义注释看起来如何?应该怎么处理?
  • 这是一个 JSR-303/Hibernate 验证器吗?
  • 这是一个 javax.persistence 验证器,我相信它是从 Hibernate 派生的,是的,JPA 实现是 Hibernate。

标签: java jpa


【解决方案1】:

问题是当您尝试持久化bar 时,您不会自动持久化它的foo。您必须在 @ManyToOne 注释中明确指定您想要级联持久化操作,或者您必须手动持久化foo

@ManyToOne(optional = false, cascade = CascadeType.PERSIST)
Foo foo;

【讨论】:

  • 仍然不调用验证,我不知道为什么。也许是因为在数据库级别,Foo 没有变化?外键列在Bar 的表中,这是您修改Foo 的条形集合时唯一改变的内容。
  • 这仅适用于持久化,如果您希望传播所有操作(例如合并、删除),则必须使用CascadeType.ALL
  • 是的,但是在我的小测试中,它甚至无法持久化。但是,整个系统几乎是一团糟,而且可能完全是其他东西阻止了它的工作。还是谢谢你。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-09
  • 2018-10-26
  • 2016-11-21
  • 2011-10-02
  • 2013-01-15
相关资源
最近更新 更多