本文介绍了MyBatis:如何绕过本地缓存并在特定选择上直接命中数据库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是 MyBatis 3.1.
当我需要绕过 MyBatis 本地缓存并直接命中 DB 时,我有两个用例.
由于 MyBatis 配置文件只有全局设置,所以不适用于我的情况,因为我需要它作为例外,而不是作为默认值.MyBatis 的属性XML 语句似乎不包含此选项.

I use MyBatis 3.1.
I have two use cases when I need to bypass MyBatis local cache and directly hit the DB.
Since MyBatis configuration file only have global settings, it is not applicable to my case, because I need it as an exception, not as a default. Attributes of MyBatis <select> XML statement do not seem to include this option.

用例 1:'select sysdate from dual'.
MyBatis 缓存导致这个在 MyBatis 会话中总是返回相同的值.当我尝试复制过时条目的情况时,这会导致我的集成测试出现问题.
我的解决方法只是使用普通的 JDBC 调用.

Use case 1: 'select sysdate from dual'.
MyBatis caching causes this one to always return the same value within a MyBatis session. This causes an issue in my integration test, when I try to replicate a situation of an outdated entry.
My workaround was just to use a plain JDBC call.

用例 2:从一个线程选择"并不总是看到另一个线程写入的值.
主题 1:

Use case 2: 'select' from one thread does not always see the value written by another thread.
Thread 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.

I occasionally receive MyException errors on a server, but can't reproduce on my local machine. In all cases the object is always in the DB. So I guess the error depends on whether the stored object was in MyBatis local cache at the first time, and waiting for 5 minutes does not help, since it never checks the actual DB.

所以我的问题是如何在 MyBatis 中解决上述用例而不回退到普通的 JDBC?
能够以某种方式向 MyBatis 发出信号,不要在特定调用(最好)或对特定查询的所有调用中使用缓存值将是首选选项,但我也会考虑任何解决方法.

So my question is how to solve the above use cases within MyBatis without falling back to the plain JDBC?
Being able just to somehow signal MyBatis not to use a cached value in a specific call (the best) or in all calls to a specific query would be the preferred option, but I will consider any workaround as well.

推荐答案

我不知道绕过本地缓存的方法,但有两种方法可以实现您的需求.

I don't know a way to bypass local cache but there are two options how to achieve what you need.

第一个选项是在 select 上设置 flushCache="true".这将在语句执行后清除缓存,以便下一个查询命中数据库.

The first option is to set flushCache="true" on select. This will clear the cache after statement execution so next query will hit database.

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

另一种选择是使用 STATEMENT 级别的本地缓存.默认情况下,在 SESSION 期间使用本地缓存(通常转换为事务).这由 localCacheScope 选项指定,并按会话工厂设置.所以这会影响所有使用这个mybatis session factory的查询.

Another option is to use STATEMENT level local cache. By default local cache is used during SESSION (which is typically translates to transaction). This is specified by localCacheScope option and is set per session factory. So this will affect all queries using this mybatis session factory.

这篇关于MyBatis:如何绕过本地缓存并在特定选择上直接命中数据库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-22 09:30