我使用MyBatis 3.1。
当我需要绕过MyBatis本地缓存并直接命中DB时,我有两个用例。
由于MyBatis配置文件只具有全局设置,因此它不适用于我的情况,因为我需要它作为一个例外,而不是作为默认设置。MyBatis XML语句的属性似乎不包括此选项。
用例1:‘从dual中选择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分钟没有帮助,因为它从不检查实际的DB。
因此,我的问题是如何在MyBatis中解决上面的用例而不回到普通的JDBC?
在特定调用中(最好)或在所有对特定查询的调用中不使用缓存值的信号MyBatis将是首选的选择,但我也会考虑任何解决办法。
发布于 2014-10-21 08:25:42
我不知道如何绕过本地缓存,但是有两个选项可以实现您所需要的。
第一个选项是在flushCache="true"上设置select。这将在语句执行后清除缓存,因此下一个查询将访问数据库。
<select id="getCurrentDate" resultType="date" flushCache="true">
SELECT SYSDATE FROM DUAL
</select> 另一种选择是使用语句级本地缓存。默认情况下,在会话期间使用本地缓存(通常转换为事务)。这是由localCacheScope选项指定的,并设置为每个会话工厂。因此,这将影响使用此mybatis工厂的所有查询。
发布于 2014-10-21 13:24:29
让我总结一下。
来自上一个答案的解决方案--查询上的'flushCache="true"‘选项--工作并解决了这两个用例。它将在每个这样的“select”之后刷新缓存,因此下一个'select‘语句将命中DB。虽然它在执行'select‘语句后在上工作,但它是可以的,因为缓存在第一个'select’之前仍然是空的。
另一个解决方案是启动一个新的会话。我使用Spring,所以它就足够用@Transactional(传播= Propagation.REQUIRES_NEW)标记一个方法了。由于MyBatis会话与相关联,这将导致每次调用该方法时都会使用新的缓存创建另一个MyBatis会话。
由于某种原因,查询中的MyBatis选项‘useCache=“”false“无法工作。
发布于 2018-03-09 16:35:29
可以使用以下Options注释:
@Options(useCache=false, flushCache=FlushCachePolicy.TRUE)https://stackoverflow.com/questions/26440362
复制相似问题