2014-10-18 40 views
4

我使用MyBatis 3.1。
我有兩個用例,當我需要繞過MyBatis本地緩存並直接命中數據庫。
因爲MyBatis配置文件只有全局設置,所以它不適用於我的情況,因爲我需要它作爲例外,而不是默認設置。 MyBatis的屬性<select> XML語句似乎不包含此選項。
MyBatis:如何繞過本地緩存,並直接命中特定的數據庫

用例1:'select double from dual'。
MyBatis緩存會導致此問題在MyBatis會話中始終返回相同的值。當我嘗試複製過時條目的情況時,這會導致我的集成測試出現問題。
我的解決方法只是使用普通的JDBC調用。

用例2:從一個線程中'select'並不總是看到另一個線程寫入的值。
線程1:

SomeObject stored = dao.insertSomeObject(obj); 
runInAnotherThread(stored.getId()); 
//complete and commit 

線程2:

//'id' received as an argument provided to 'runInAnotherThread(...)' 
SomeObject stored = dao.findById(id); 
int count = 0; 
while(stored == null && count < 300) { 
    ++count; 
    Thread.sleep(1000); 
    stored = dao.findById(id); 
} 
if (stored == null) { 
    throw new MyException("There is no SomeObject with id="+id); 
} 

我偶爾會在服務器上接收MyException錯誤,但我的本地機器上無法重現。在所有情況下,對象總是在數據庫中。所以我猜這個錯誤取決於第一次存儲的對象是否在MyBatis本地緩存中,等待5分鐘沒有幫助,因爲它從不檢查實際的數據庫。

所以我的問題是如何解決MyBatis中的上述用例,而不會回落到純JDBC?
只能以某種方式指示MyBatis不要在特定的調用中使用緩存的值(最好)或者在所有調用特定查詢的情況下都是首選,但我也會考慮任何解決方法。

回答

7

我不知道繞過本地緩存的方法,但有兩個選擇如何實現你所需要的。

第一個選項是在select上設置flushCache="true"。這將在語句執行後清除緩存,所以下一個查詢將會碰到數據庫。

<select id="getCurrentDate" resultType="date" flushCache="true"> 
     SELECT SYSDATE FROM DUAL 
    </select> 

另一個選擇是使用STATEMENT級別的本地緩存。默認情況下,本地緩存在SESSION期間使用(通常轉換爲事務)。這由localCacheScope選項指定,並在每個會話工廠中設置。所以這會影響使用這個mybatis會話工廠的所有查詢。

+1

的「flushCache =‘真’」的作品的確,謝謝,相信。正如你剛纔注意到的,第二種選擇是全球性的,所以我會避免它。 – Alexander 2014-10-21 13:15:53

5

讓我總結一下。
解決方案來自上一個回答'flushCache =「true」'選項在查詢中,可以解決這兩種情況。它會在每次這樣的「select」之後刷新緩存,所以下一個「select」語句將會觸發DB。雖然之後運行,但是'select'語句被執行,因爲緩存在第一個'select'前是空的。

另一個解決方案是開始一個新的會話。我使用Spring,因此只需使用@Transactional(propagation = Propagation.REQUIRES_NEW)即可標記方法。由於MyBatis會話與Spring事務綁定,因此每次調用該方法時都會導致使用新緩存創建另一個MyBatis會話。

由於某種原因,MyBatis選項'useCache =「false」'在查詢中不起作用。

1
由羅馬和亞歷山大答案

除了有這一個更多的解決方案:

Configuration configuration = MyBatisUtil.getSqlSessionFactory().getConfiguration(); 
      Collection<Cache> caches = configuration.getCaches(); 

      //If you have multiple caches and want a particular to get deleted.   
      // Cache cache = configuration.getCache("PPL"); // namespace of particular XML 
      for (Cache cache : caches) { 
       Lock w = cache.getReadWriteLock().writeLock(); 
       w.lock(); 
       try { 
        cache.clear(); 
       } finally { 
        w.unlock(); 
       } 
      } 
0

以下Options標註可用於:

@Options(useCache=false, flushCache=FlushCachePolicy.TRUE) 
相關問題