我們遇到了一個問題,我們必須維護一個日期字段 - 並最好保留其值 - 其中日期字段依賴於其他實體'狀態。用JPA2 + Hibernate + Spring解決這個問題的正確方法是什麼?更新依賴於其他實體狀態的@Entity字段的正確方法
基本上,我們有三個實體,我們稱它們爲Parent
,Child
和Conf
。 dependentDate
由依賴於其他實體狀態的複雜業務規則計算得出。具體來說,應該是Parent#date
減去Conf#delay
跳過所有周末或節假日(持續數據)。
問題是,只要Parent#date
發生變化,應該重新計算所有孩子的dependentDate
。每當Child
對象的conf
發生更改時也會發生這種情況。目前,有一種基於Child
對象關係計算新日期的服務方法(我們稱之爲calculateDate()
)。
我們面臨着應該計算字段值的問題。我想出了三種可能的解決方案。哪些這些 - 或者可能是別的 - 是更新依賴於其他實體狀態的實體字段的首選方式?
- 一個JPA
EntityListener
- 並不鼓勵這樣的JPA2規範,因爲EntityListeners不應訪問其他實體
- 領域將永遠是正確的
- 一個Spring AOP的方面的更新
- 該邏輯被隱藏在其他一些類別中,不容易看到
- 的切入點不抓的風險都堅持/更新事件
- 每個開發者爲自己
- 始終,更新或者父母或子女類的實例時,開發者必須記住調用該服務的
calculateDate()
方法 - 這應該在道或服務層?顯影劑忘記加呼叫的
- 風險,從而導致錯誤的狀態
- 始終,更新或者父母或子女類的實例時,開發者必須記住調用該服務的
下面的示例示出了其中省略註解配置的實體關係。
的實體
public class Parent {
LocalDate date;
Set<Child> children; // one-to-many
}
public class Conf {
int delay;
}
public class Child {
LocalDate dependentDate;
Conf conf; // many-to-one
Parent parent; // many-to-one
}
這不應該是一個答案,但更多的是「選項4」:您可以在數據庫中添加一個觸發器,用於在更新其他表格時更新日期字段。這當然只適用於以下情況:a)你的dbms支持觸發器,b)你願意將業務邏輯移出主軟件,c)你的實體是「無狀態的」(就像在彈簧mvc設置中一樣)。 – realsim
@realsim「無狀態」實體的含義是什麼?正如我所看到的,實體只是一個狀態(免責聲明,我知道JPA但不是Spring) – SJuan76
我的意思是在提交hibernate會話之後,它不會再被使用(因爲觸發器實體不在會議認爲他們的狀態)。如果會話將被重用,它將以StaleObjectStateException結束。但是如果會話因爲請求/響應完成而關閉,並且下一個請求會創建另一個會話,那麼這種方法就沒有問題。 - 我不喜歡自己移動業務邏輯,但有時觸發器是必需的... – realsim