MyBatis一級キャッシュおよび失効
23070 ワード
MyBatisはクエリーキャッシュメカニズムを提供し、大量の重複クエリーに対してキャッシュを使用することでデータベースの圧力を軽減します.
公式サイト
MyBatisには強力なトランザクション・クエリー・キャッシュ・メカニズムが内蔵されており、構成とカスタマイズが容易です.より強力で構成しやすいように、MyBatis 3のキャッシュ実装を大幅に改善しました.デフォルトでは、ローカルのセッションキャッシュのみが有効になり、1つのセッションのデータのみがキャッシュされます.グローバル2次キャッシュを有効にするには、SQLマッピングファイルに行を追加するだけです.
MyBatisの一級キャッシュはセッションベースであり,異なるセッション間で共有できない.2次キャッシュはnamespaceに基づいており、すべてのセッションを共有できます.
一級キャッシュテスト
一級キャッシュはデフォルトでオンであり、オフにすることはできません.
MyBatisのプロファイルはここには貼られていません.
DemoDao
CacheDemo
出力は次のとおりです.
1回目のクエリと2回目のクエリは同じSqlSessionであり,2回のクエリの間にUPDATE操作が1回行われ,クエリのデータは依然として古い.
出力されたログからも、2回目のクエリはSQLを実行するのではなく、キャッシュから直接返される結果が表示されます.
Springと統合すると、1つのキャッシュが無効になりますか?
MyBatisを単独で使用する場合、SqlSessionの実装クラスはDefaultSqlSessionであり、Springと統合する場合、MyBatisはSqlSessionTemplate実装クラスを提供する.
SqlSessionTemplateには、SqlSessionInterceptorという内部クラスがあります.
ソースコードは次のとおりです.
SQLを実行するたびに、SqlSessionInterceptorはsqlSessionを閉じます.
これにより、実行するたびにsqlSessionが異なり、一級キャッシュはsqlSessionに基づいており、キャッシュが失効し、毎回データベースからクエリーされます.
公式サイト
MyBatisには強力なトランザクション・クエリー・キャッシュ・メカニズムが内蔵されており、構成とカスタマイズが容易です.より強力で構成しやすいように、MyBatis 3のキャッシュ実装を大幅に改善しました.デフォルトでは、ローカルのセッションキャッシュのみが有効になり、1つのセッションのデータのみがキャッシュされます.グローバル2次キャッシュを有効にするには、SQLマッピングファイルに行を追加するだけです.
MyBatisの一級キャッシュはセッションベースであり,異なるセッション間で共有できない.2次キャッシュはnamespaceに基づいており、すべてのセッションを共有できます.
一級キャッシュテスト
一級キャッシュはデフォルトでオンであり、オフにすることはできません.
MyBatisのプロファイルはここには貼られていません.
DemoDao
public interface DemoDao {
@Select("select * from t where a = 1")
Map<String,Object> selectOne();
@Update("update t set c = 2 where a = 1")
int updateOne();
}
CacheDemo
public class CacheDemo {
SqlSessionFactory factory;
@Before
public void init() throws IOException {
String resource = "mybatis.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
factory = new SqlSessionFactoryBuilder().build(inputStream);
if (inputStream != null) {
inputStream.close();
}
}
@Test
public void test() throws IOException {
SqlSession sqlSession = factory.openSession();
System.out.println(" ...");
select(sqlSession);
System.out.println(" ...");
update();
System.out.println(" ...");
select(sqlSession);
}
//select
void select(SqlSession session) throws IOException {
DemoDao mapper = session.getMapper(DemoDao.class);
Map<String, Object> map = mapper.selectOne();
System.out.println(map);
}
//update
void update() throws IOException {
SqlSession session = factory.openSession();
DemoDao mapper = session.getMapper(DemoDao.class);
mapper.updateOne();
session.commit();
session.close();
}
}
出力は次のとおりです.
...
DEBUG [main] - ==> Preparing: select * from t where a = 1
DEBUG [main] - ==> Parameters:
TRACE [main] - <== Columns: a, b, c
TRACE [main] - <== Row: 1, 1, 1
DEBUG [main] - <== Total: 1
{a=1, b=1, c=1}
...
DEBUG [main] - ==> Preparing: update t set c = 2 where a = 1
DEBUG [main] - ==> Parameters:
DEBUG [main] - <== Updates: 1
DEBUG [main] - ==> Preparing: select * from t where a = 1
DEBUG [main] - ==> Parameters:
TRACE [main] - <== Columns: a, b, c
TRACE [main] - <== Row: 1, 1, 2
DEBUG [main] - <== Total: 1
:{a=1, b=1, c=2}
...
{a=1, b=1, c=1}
1回目のクエリと2回目のクエリは同じSqlSessionであり,2回のクエリの間にUPDATE操作が1回行われ,クエリのデータは依然として古い.
出力されたログからも、2回目のクエリはSQLを実行するのではなく、キャッシュから直接返される結果が表示されます.
Springと統合すると、1つのキャッシュが無効になりますか?
MyBatisを単独で使用する場合、SqlSessionの実装クラスはDefaultSqlSessionであり、Springと統合する場合、MyBatisはSqlSessionTemplate実装クラスを提供する.
SqlSessionTemplateには、SqlSessionInterceptorという内部クラスがあります.
ソースコードは次のとおりです.
private class SqlSessionInterceptor implements InvocationHandler {
private SqlSessionInterceptor() {
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
SqlSession sqlSession = SqlSessionUtils.getSqlSession(SqlSessionTemplate.this.sqlSessionFactory, SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator);
Object unwrapped;
try {
Object result = method.invoke(sqlSession, args);
if (!SqlSessionUtils.isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
sqlSession.commit(true);
}
unwrapped = result;
} catch (Throwable var11) {
unwrapped = ExceptionUtil.unwrapThrowable(var11);
if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
sqlSession = null;
Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException)unwrapped);
if (translated != null) {
unwrapped = translated;
}
}
throw (Throwable)unwrapped;
} finally {
if (sqlSession != null) {
// SQL, sqlSession
SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
}
}
return unwrapped;
}
}
SQLを実行するたびに、SqlSessionInterceptorはsqlSessionを閉じます.
これにより、実行するたびにsqlSessionが異なり、一級キャッシュはsqlSessionに基づいており、キャッシュが失効し、毎回データベースからクエリーされます.