2015-10-19 61 views
7

我看到getOne()被延遲加載,findOne()立即獲取整個實體。我已經檢查了調試日誌,並且甚至在我的sql服務器上啓用了監視來查看執行的語句,我發現getOne()findOne()都生成並執行相同的查詢。但是,當我使用getOne()時,這些值最初爲空(當然,id除外)。CrudRepository findOne()和JpaRepository getOne()之間的差異

所以任何人都可以告訴我,如果兩個方法都在數據庫上執行相同的查詢,爲什麼我應該使用另一個呢?我基本上正在尋找一種方式來獲取一個實體,而不會獲得它的所有子/屬性。

EDIT1:

Entity code

道代碼:

@Repository 
public interface FlightDao extends JpaRepository<Flight, Long> { 
} 

Debugging log findOne() vs getOne()

EDIT2:

感謝Chlebik,我能夠發現問題。就像Chlebik所說,如果您嘗試訪問由getOne()獲取的實體的任何屬性,則將執行完整查詢。就我而言,我在調試時檢查行爲,一次移動一行,我完全忘記了在調試IDE時爲了調試目的而嘗試訪問對象屬性(或者至少這是我認爲正在發生的事情),因此調試觸發器完整的查詢執行。我停止調試,然後檢查日誌和一切似乎是正常的。

getOne() VS findOne()(此日誌從MySQL general_log拍攝,而不是冬眠。

Debugging log

No debugging log

回答

6

這只是一個猜測,但 '純JPA' 存在的EntityManager的方法稱爲getReference。它的目的是檢索只有ID的實體,其用途主要是爲了指示存在而不需要檢索整個實體,也許c頌歌會告訴更多:

// em is EntityManager 
Department dept = em.getReference(Department.class, 30); // Gets only  entity with ID property, rest is null 
Employee emp = new Employee(); 
emp.setId(53); 
emp.setName("Peter"); 
emp.setDepartment(dept); 
dept.getEmployees().add(emp); 
em.persist(emp); 

我認爲然後getOne有異曲同工之妙。爲什麼生成的查詢與您要求的相同?那麼,JPA聖經中的AFAIR - Mike Keith和Merrick Schincariol的JPA2 - 幾乎每個段落都包含「行爲取決於供應商」之類的內容。

編輯:

我已經設置了我自己的設置。最後,我得出結論,如果您以任何方式干擾獲取getOne(甚至去entity.getId())的實體,它會導致SQL執行。雖然如果您僅將它用於創建代理(例如,如上面代碼中所示的關係指示符),則不會發生任何事情,並且不會執行額外的SQL。所以我假設在你的服務類中你對這個實體做了一些事情(使用getter,記錄一些東西),這就是爲什麼這兩個方法的輸出看起來相同。

ChlebikGitHub with example code
SO helpful question #1
SO helpful question #2

+0

感謝您的信息。實際上'getOne()'做的是調用'getReference()'。我真的很困惑,因爲正如我前面說過的,這兩種方法生成並執行相同的查詢!所以也許它與你所說的MySQL有關?我真的希望有人能證實這一點。如果查詢在正常情況下的兩種方法之間有所不同,您是否有任何想法? – prettyvoid

+0

供應商並不意味着例如。 MySQL,但Hibernate/TopLink /無論你使用什麼。我假設正在執行的查詢是基於您的實體中定義的關係,並可能通過JPA實現進行優化。與簡單的實體恕我直言,沒有太多的區別,提取處理程序之間的實體(如** getReference **)和實際檢索所有數據。 – Chlebik

+0

我必須得到一個引用,因爲我試圖獲取的實體有很多子實體,當我只需要實體的ID時,獲取整個事物的工作量很大。讓我們等一會兒,也許有人可以告訴我們發生了什麼。再次感謝 – prettyvoid