我需要在spring-jpa(hibernate)驅動的web應用程序中實現一個實體的GetOrCreate(我稱之爲ensureExists)。
我有一個分層的應用程序(WS/Services/DAL/Datastore),我想在服務層(spring驅動)中實現這個功能。
的基本思路是:如何使用JPA會話實現併發GetOrCreate?
- 查找實體
- 如果找到返回。
- 否則堅持實體。
- 如果一切正常返回它。
- 如果發生了唯一約束違規,請嘗試再次查找實體並將其返回。
問題的事實,一旦有異常拋出Hibernate的Session應該關閉並重新打開(從Session的documentation),這使得第5步無效,但我還是想封裝在服務層這一邏輯(出現並沒有它駐留在DAL或WS中)。
我很樂意聽到關於如何解決這個問題的建議,我有一個想法,但我希望在發佈之前聽到一些意見,以避免向答案傾斜。
預先感謝
更新
溶液我想到如下:
重構階段3到封裝作用域服務具有單一ensureExists方法(使用泛型),它接受所述道這種類型和實體,並具有REQUIRES_NEW
的傳播。這個方法會嘗試持久化,如果失敗,當然會拋出一個將被原始服務捕獲的異常,並且如果該異常被拋出,它將嘗試持久化。
我很想談談如何以其他方式實現這一點。
如果沒有人會在幾天內另外提出建議,我會以代碼示例的形式發佈此答案並接受它。
我會按照你的計劃去做,除非我將步驟1到步驟4放在REQUIRES_NEW的服務中。 – 2012-01-20 07:12:58
@JB Nizet爲什麼你認爲步驟1,2,4需要進行交易?另外,在我看來,邏輯上只有第3步處於不同的抽象層次,所以有理由讓它坐在不同的服務中。所有其他步驟都具有相同的抽象級別(我認爲)。 – Ittai 2012-01-20 13:07:34
我剛剛發現它有一個「getOrCreate」方法,它可以拋出異常,並且如果我想從外部重試,可以更清晰。它也將特定用例的重試邏輯(可以完全通用,提取給代理或攔截器)分離出來。而且它還允許使用創建的實體執行其他操作,而不僅僅是返回它。在你的系統中,你得到的實體被連接,如果被創建,則被分離。 – 2012-01-20 13:12:52