2012-11-27 68 views
19

我用一個例子來展示這個問題。Spring Data JPA - 爲什麼對返回實體的更改會自動保留?

斷言,我們有一個存儲庫,如以下:

public interface ExampleObjectRepository extends CrudRepository<ExampleObject, Long> { 

} 

通過延伸JpaRepository接口,所述ExampleObject庫繼承的以下方法:

T findOne(ID id); 

現在,我觀察到,如果在調用此方法後收到對ExampleObject的引用,則對該方法進行的任何操作都會自動保存到數據庫中,例如:

ExampleObject pointInCase = exampleObjectRepository.findOne(1L); 
pointInCase.setName("Something else"); 

閱讀這個問題,我明白這表明ExampleObject實例是not detached

這違背了我的期望。我本來期望,我會需要使用從CrudRepository繼承了保存方法,以保存更改:

T save(T entity); 

會有人還跟確認對象從Spring數據JPA庫返回保持標準附,並解釋如何使用API​​來標記存儲庫中的方法,以便它只返回分離的引用?

我想象一下,當它與所說的save(T entity)方法一起使用時,更改實體的狀態也可能會改變它的定義,所以我也希望瞭解如何處理更新標識。

回答

14

這是JPA的基本原理。您使用附加(託管)實體進行工作,並且對這些管理實體所做的每個修改都會自動保持不變。

如果您不希望您的更改持久,則不要進行更改或回滾事務。

處理分離的實體將是一場噩夢,因爲它會阻止延遲加載所有關聯。你可以隨時致電EntityManager.detach()對你的實體,但我真的不會那樣做。試着瞭解它是如何工作和處理的。缺點比益處多得多。其中之一是,您甚至不必考慮保存複雜業務邏輯可能做的所有更改,因爲JPA透明地爲您完成了所有這些更改。

+0

感謝您的意見 - 他們肯定與辦公室其他意見一致!但是,如果將幾個POJO操作作爲事務的一部分進行,此行爲是否會打破該方法的事務性質? – 8bitjunkie

+1

爲什麼呢?您開始一個交易,對任意數量和種類的實體進行任意數量的修改,然後提交交易。要麼所有更改都已提交,要麼所有更改都會回滾。方法的事務方面也適用於它調用的每一個內部方法:事務上下文被傳播。 –

+0

所以...調用'save'方法是不必要的,除非你分離?或者我應該調用另一個方法來確保JPA關閉事務而不是回滾? – kiedysktos

5

如果您的事務處理器的作用域爲存儲庫,則可以使您的Repository返回分離的實體。即你的事務從入庫開始,並在代碼退出存儲庫時關閉。

如果你這樣工作,你必須小心所有必要的數據一次加載,否則你會得到懶惰的初始化異常。但是在許多情況下,我認爲這是可取的,因爲它可以讓您控制何時加載數據,以及在使用JPA時通過手指輕鬆滑動。

對於修改,我使用了一個不同的事務範圍,它包裝了加載,更改(和隱式持久化)的完整過程。

相關問題