我使用MyBatis 3.1。
当我需要绕过MyBatis本地缓存并直接命中数据库时,我有两个用例。
由于MyBatis配置文件只有全局设置,因此不适用于我的情况,因为我需要它作为例外,而不是默认情况。 MyBatis的属性< select> XML语句似乎不包含此选项。
用例1 :'从双重选择sysdate'。
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错误,但无法在本地计算机上重现。在所有情况下,对象始终在DB中。所以我猜错误取决于第一次存储的对象是否在MyBatis本地缓存中,等待5分钟没有帮助,因为它从不检查实际的数据库。
所以我的问题是如何在不退回普通JDBC的情况下解决MyBatis中的上述用例?
能够以某种方式告知MyBatis不在特定调用中使用缓存值(最好)或在特定查询的所有调用中将是首选选项,但我也会考虑任何解决方法。
答案 0 :(得分:8)
我不知道如何绕过本地缓存,但有两种选择如何实现您的需求。
第一个选项是在flushCache="true"
上设置select
。这将在语句执行后清除缓存,以便下一个查询将命中数据库。
<select id="getCurrentDate" resultType="date" flushCache="true">
SELECT SYSDATE FROM DUAL
</select>
另一种选择是使用STATEMENT级本地缓存。默认情况下,在SESSION期间使用本地缓存(通常转换为事务)。这由localCacheScope
选项指定,并根据会话工厂设置。因此,这将影响使用此mybatis会话工厂的所有查询。
答案 1 :(得分:6)
让我总结一下。
上一个答案的解决方案&#39; flushCache =&#34; true&#34; &#39;查询选项,工作并解决两个用例。它会在每次选择&#39;之后刷新缓存,以便下一次选择&#39;声明会打到DB。虽然之后 ,但选择&#39;语句被执行,它是正常的,因为在第一次选择之前缓存是空的。
另一个解决方案是开始一个新会话。我使用Spring,所以它足以用 @Transactional(propagation = Propagation.REQUIRES_NEW) 标记方法。由于MyBatis会话与Spring事务相关联,因此每次调用该方法时都会导致创建另一个带有新缓存的MyBatis会话。
出于某种原因,MyBatis选项&#39; useCache =&#34; false&#34; &#39;在查询中不起作用。
答案 2 :(得分:3)
可以使用以下Options
注释:
@Options(useCache=false, flushCache=FlushCachePolicy.TRUE)
答案 3 :(得分: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();
}
}