2015-05-10 32 views
3

我有一堆JPA DAOs即將遷移到Spring Data JPA。我的一些DAOS設置了二級/查詢緩存。如何使用二級緩存將我的JPA DAO遷移到Spring Data?

我有一個過程,我只在我的查詢中檢索ID,然後使用findByID()查找實體。這樣,只有id在不同的查詢緩存中相乘,並且整個實體位於第二級緩存中。

例子:

@NamedQuery(name = "SystemUser.findByEmail", 
      query = "SELECT u.id FROM SystemUser u WHERE email=:email"), 
… 

public SystemUser findByEmail(String email) { 

    TypedQuery<Long> q = getEntityManager().createNamedQuery("SystemUser.findByEmail", Long.class); 
    q.setParameter("email", email); 
    q.setHint("org.hibernate.cacheable", true); 
    q.setHint("org.hibernate.cacheRegion", "query.systemUser"); 

    List<Long> res = q.getResultList(); 

    if (res != null && res.size() > 0) { 
     return findById(res.get(0)); 
    } 

    return null; 
} 

我有幾個findBy… - 方法,都做這樣的。這感覺是保持緩存內存消耗降低的好方法。

我對Spring Data JPA業務很陌生,但我不明白我會如何去實現這一點? @Cacheable註解似乎只是爲了處理查詢緩存,這對我來說會複製每個查詢緩存中的實體?

有沒有辦法用Spring Data做到這一點?指針將非常感激。

+1

'@ Cacheable'與查詢或二級緩存無關。它是關於緩存方法調用的結果,並且可以使用或不使用hibernate。例如,您也可以使用它來緩存長計算的結果。此外,您的代碼似乎不必要地複雜,爲什麼不簡單地返回'SystemUser'而不是執行2個查詢,您可能已經觸發了單個查詢。看起來像一個不成熟的優化出錯了? –

+0

假設我在Systemuser中有5個方法,都在執行「findby ...」不同的參數,所有緩存。使用我的解決方案,只有ID存儲在每個查詢緩存中,並且只有一個'full'系統用戶實例存儲在第二級緩存中,所有5個方法將通過findById檢索。我希望這是有道理的。 – Mathias

回答

4

在Spring Data JPA中,只需創建一個findByEmail方法,並且Spring Data JPA都會找到您的命名查詢或自己創建一個。

public class SystemUserRepository extends CrudRepository<SystemUser, Long> { 

    SystemUser findByEmail(String email); 
} 

應該是所有你需要的查詢執行和所需的結果。現在用@QueryHints您可以添加您現在設置的提示。

public class SystemUserRepository extends CrudRepository<SystemUser, Long> { 

    @QueryHints(
     @QueryHint(name="org.hibernate.cacheable", value="true"), 
     @QueryHint(name="org.hibernate.cacheRegion", value="query.systemUser")  ) 
    SystemUser findByEmail(String email); 
} 

結果將被緩存,並且用戶仍然來自二級緩存(如果可用,否則創建)。當然假設你的實體是@Cacheable

關於2種不同的緩存如何工作(一起)的一個很好的閱讀可以找到here。查詢緩存如何工作的一小段代碼。

查詢緩存看起來概念等,其中的關鍵是通過查詢文本和參數值組成的哈希表,並的值是實體ID的匹配查詢一個列表:

如果您想要更復雜的邏輯(並真正實現您所做的優化),您可以始終實施own repository

+0

嘿謝謝你的快速回復。我有一個存儲庫解決方案正在運行,但正如您所提到的,我以前的緩存解決方案不是。很高興聽到@queryhints,但正如你所說,不會幫助我緩存性能的調整,我不得不讓每個查詢加載所有的數據,導致數據重複爲每個地區的查詢緩存。所以唯一的方法是實現我自己的存儲庫? OK ... :) – Mathias

+0

查詢的結果被緩存,實際的用戶實例仍應來自通用緩存。唯一的區別是你緩存可能會少一些,但是由於附加的查詢會引入額外的開銷,當你使用多個結果做這些事情時可能會更糟,因爲這會導致1 + N選擇問題。 (1查詢ID,每行另一個查詢以獲得完整結果)。恕我直言,你正試圖優化一些東西,但正在嘗試解決更多的問題和複雜性。 –

+0

唯一有一個附加查詢是第一次,其他時間將在二級緩存中。我知道1 + n問題,這就是爲什麼我們只爲了獲得獨特結果而做的。對於那些,我們已經注意到內存和性能的改進。 – Mathias

相關問題