mybatis cache
mybatis的cache是基于statement的, 有人也称之为query cache,以有别于基于id的cache。你需要指定哪些statements来useCache, 哪些statements触发flushCache.
一旦触发了flushCache, cache将invalidate并清空,下次的查询都将从数据库查询,并放入cache
限制:
- 同一个应用,一旦使用cache,需遵循:
- 查询:先查询cache,命中返回; 未命中,查询数据库后放入cache
- 修改:修改数据库,flush cache
- 一旦修改了cache区域中数据,一定要flush,否则会出现cache与数据库不一致
- 使用cache的应用,外部程序(工具)直接修改数据库一定要慎重,因为极有可能导致数据不一致
下面是一个例子:
<?xml version=”1.0” encoding=”UTF-8” ?>
<!DOCTYPE configuration
PUBLIC “-//mybatis.org//DTD Config 3.0//EN”
“http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name=”cacheEnabled” value=”true”/>
</settings>
<environments default=”development”>
<environment id=”development”>
<transactionManager type=”JDBC”/>
<dataSource type=”POOLED”>
<property name=”driver” value=”com.mysql.jdbc.Driver”/>
<property name=”url” value=”jdbc:mysql://localhost:3306/test”/>
<property name=”username” value=”root”/>
<property name=”password” value=””/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource=”SqlMapper.xml”/>
</mappers>
</configuration>
<?xml version=”1.0” encoding=”UTF-8” ?>
<!DOCTYPE mapper
PUBLIC “-//mybatis.org//DTD Mapper 3.0//EN”
“http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace=”person”>
<cache eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
<select id="selectPerson" resultType="java.util.HashMap" flushCache="false" useCache="true">
select * from person
</select>
<insert id="insertPerson">
insert into person values ('ccccc', 23, 'shenzhen')
</insert>
<insert id="insertStaff">
insert into staff values ('richard')
</insert>
</mapper>
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;
public class Main {
private static SqlSessionFactory sqlSessionFactory;
private static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
public static void main(String[] args) throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
String command = null;
while ((command = br.readLine()) != null) {
SqlSession sqlSession = sqlSessionFactory.openSession();
if(command.equals("q")) {
System.out.println("sql query:");
List<Map> list = sqlSession.selectList("person.selectPerson");
System.out.println(list);
} else if(command.equals("i")) {
System.out.println("sql insert:");
sqlSession.insert("person.insertPerson");
} else if(command.equals("is")) {
System.out.println("sql insert:");
sqlSession.insert("person.insertStaff");
}
sqlSession.commit();
sqlSession.close();
}
}
}
如何测试:
- 控制台输入"q"触发查询,可以看到首次查询,会使用sql从数据库查询
- 这时,我们控制台或数据库客户端(如mysql客户端)再向数据库中插入一些数据
- 再次控制台输入"q"再次触发查询,日志显示,这次cache命中,直接从cache中读数据,程序外部(客户端)插入的数据并没有得到。很容易解释,因为这些外部的插入,mybatis并不知道。
- 控制台输入"i"触发插入数据,然后再输入"q"触发查询,这次可以看到,会使用sql从数据库查询。可见insert触发了flushCache
- 控制台输入"q"触发查询,发现cache命中, 不执行SQL
- 控制台输入"is"触发插入另一个表的数据,然后再输入"q"触发查询,可以看到这时同样使用sql从数据库查询。可见虽然是不同的表的插入,也将flush整个cache, 因为他们共用位于同一个SqlMapper的namespace中的cache
- 控制台输入"q"触发查询,发现cache命中, 不执行SQL
q
sql query:
2015-11-06 21:39:26,103 [DEBUG] (org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.debug(JakartaCommonsLoggingImpl.java:54)) -
Cache Hit Ratio [person]: 0.0
2015-11-06 21:39:26,417 [DEBUG] (org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.debug(JakartaCommonsLoggingImpl.java:54)) -
==> Preparing: select * from person
2015-11-06 21:39:26,447 [DEBUG] (org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.debug(JakartaCommonsLoggingImpl.java:54)) -
==> Parameters:
2015-11-06 21:39:26,463 [DEBUG] (org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.debug(JakartaCommonsLoggingImpl.java:54)) -
<== Total: 0
[]
i
sql insert:
2015-11-06 21:39:42,303 [DEBUG] (org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.debug(JakartaCommonsLoggingImpl.java:54)) -
==> Preparing: insert into person values (‘ccccc’, 23, ‘shenzhen’)
2015-11-06 21:39:42,304 [DEBUG] (org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.debug(JakartaCommonsLoggingImpl.java:54)) -
==> Parameters:
2015-11-06 21:39:42,305 [DEBUG] (org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.debug(JakartaCommonsLoggingImpl.java:54)) -
<== Updates: 1
q
sql query:
2015-11-06 21:39:44,711 [DEBUG] (org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.debug(JakartaCommonsLoggingImpl.java:54)) -
Cache Hit Ratio [person]: 0.0
2015-11-06 21:39:44,712 [DEBUG] (org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.debug(JakartaCommonsLoggingImpl.java:54)) -
==> Preparing: select * from person
2015-11-06 21:39:44,712 [DEBUG] (org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.debug(JakartaCommonsLoggingImpl.java:54)) -
==> Parameters:
2015-11-06 21:39:44,718 [DEBUG] (org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.debug(JakartaCommonsLoggingImpl.java:54)) -
<== Total: 1
[{city=shenzhen, name=ccccc, age=23}]
q
sql query:
2015-11-06 21:39:50,878 [DEBUG] (org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.debug(JakartaCommonsLoggingImpl.java:54)) -
Cache Hit Ratio [person]: 0.3333333333333333
[{city=shenzhen, name=ccccc, age=23}]
is
sql insert:
2015-11-06 21:40:00,431 [DEBUG] (org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.debug(JakartaCommonsLoggingImpl.java:54)) -
==> Preparing: insert into staff values (‘richard’)
2015-11-06 21:40:00,432 [DEBUG] (org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.debug(JakartaCommonsLoggingImpl.java:54)) -
==> Parameters:
2015-11-06 21:40:00,439 [DEBUG] (org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.debug(JakartaCommonsLoggingImpl.java:54)) -
<== Updates: 1
q
sql query:
2015-11-06 21:40:03,310 [DEBUG] (org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.debug(JakartaCommonsLoggingImpl.java:54)) -
Cache Hit Ratio [person]: 0.25
2015-11-06 21:40:03,315 [DEBUG] (org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.debug(JakartaCommonsLoggingImpl.java:54)) -
==> Preparing: select * from person
2015-11-06 21:40:03,316 [DEBUG] (org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.debug(JakartaCommonsLoggingImpl.java:54)) -
==> Parameters:
2015-11-06 21:40:03,317 [DEBUG] (org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.debug(JakartaCommonsLoggingImpl.java:54)) -
<== Total: 1
[{city=shenzhen, name=ccccc, age=23}]
q
sql query:
2015-11-06 21:40:04,337 [DEBUG] (org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl.debug(JakartaCommonsLoggingImpl.java:54)) -
Cache Hit Ratio [person]: 0.4
[{city=shenzhen, name=ccccc, age=23}]