2017-01-21 57 views
1

我有一個春天JPA的數據存儲庫這樣的方法:@Transactional(唯讀=真)VS @QueryHints

//@QueryHints({ @QueryHint(name = "org.hibernate.readOnly", value = "true") }) 
@Transactional(readOnly = true) 
Account findByUsername(String username); 

Account髒,Hibernate試圖刷新它調用此方法時 - 我不想要。我認爲將其設置爲@Transactional(readOnly = true)可能有助於此,但事實並非如此。有趣的是使用@QueryHints與具體的冬眠提示確實工作。現在我想知道爲什麼。 @Transactional(readOnly=true)不應該有相同的效果?

回答

0

如果我們想堅持到非供應商的特定方法,你的話,我會嘗試:

選項1

@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) 
Account findByUsername(String username); 

下面我們就運行任何事務之外的查詢,這樣就不會影響持久性上下文的現有狀態。如果這種情況適合這種配置,請考慮一下。

選項2

我假設你正在做在當前事務中的其他一些修改您查詢用戶之前。我建議,然後設置刷新模式提交你的查詢(或實體管理器):

EntityManager em; 
Account findByUsername(String username){ 
    em.setFlushMode(FlushModeType.COMMIT); 

    // perform the query 
} 

OR

EntityManager em; 
Account findByUsername(String username){ 
    Query query = em.createQuery(..); 
    query.setFlushMode(FlushModeType.COMMIT); 

    // perform the query 
} 

提交刷新模式告訴持久性提供的查詢不改變的數據重疊在持久性上下文中,所以它不需要做任何事情來獲得正確的結果。

在查詢本身上設置刷新模式是一種可取的方法。

更新:選擇3

作爲最後的手段,你可以設置在覈心配置本身:

<property name="org.hibernate.flushMode" value="COMMIT"/> 

現在,這是使用的時候你不能訪問實體管理器和設置手動清洗模式。

+0

選項2b聽起來很有趣,但我使用Spring Data Repositories,其中Spring Data根據接口方法名自動生成查詢。所以我沒有把實際的查詢拿到手中。因此,我想我可以通過註釋添加該提示,Spring會爲我提供它並將其設置爲它生成的查詢。當然,我可以創建自己的Repository Impl並在那裏做這些工作,但我很懶惰:)。 – javg

+0

我明白了你的觀點,但隨着自動配置的方便,需要處理的定製案例的痛苦。工具不能考慮你想做的所有事情。想象一下,沒有人會需要開發人員了.. –

+0

多一個選項來到我的腦海 –