2013-05-28 31 views
-3

我有以下情形:JPA:上@OneToMany字段的自定義約束

@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並通過調用其添加到現有的Foobar.setFoo(foo)setFoo確保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的收藏。

+0

首先'mappedBy'期待字段名(String)而不是類,這可能是一個錯字。 –

+0

它是固定的。這是部分來自內存的問題的再現。 –

+0

我不明白。你的自定義註釋是怎樣的?應該怎樣處理? –

回答

0

問題是,當您嘗試堅持bar時,您不會自動保留foo。您必須在@ManyToOne註釋中明確指定要級聯持久性操作,否則必須手動持續foo

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

這可能工作。我會嘗試一下並讓你知道。 –

+0

仍然不會調用驗證,我不明白爲什麼。也許是因爲在數據庫層面上,'Foo'沒有改變?外鍵列在'Bar'表中,這是修改'Foo'的條形集合時唯一的變化。 –

+0

如果你想要傳播所有操作(比如合併,刪除),那麼你只能使用'CascadeType.ALL'。 –