前言
Mybatis缓存分为一级缓存,和二级缓存,同时可以配置相关缓存。
一级缓存
一级缓存是在SqlSession上的缓存,二级缓存是在SqlSessionFactory上的缓存。默认情况下,也就是没有任何配置的时候,Mybatis会自动开启一级缓存。
测试一下,首先在没有任何配置的情况下,测试以及缓存,我们对同一个sql连续调用两次,如图所示:
package com.learn.ssn.chapter3.main;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import com.learn.ssn.chapter3.mapper.RoleMapper;
import com.learn.ssn.chapter3.pojo.Role;
import com.learn.ssn.chapter3.utils.SqlSessionFactoryUtils;
public class Chapter3Main {
public static void main(String[] args) {
Logger logger = Logger.getLogger(Chapter3Main.class);
SqlSession sqlSession = null;
try{
sqlSession = SqlSessionFactoryUtils.openSqlSession();
RoleMapper rolemapper = sqlSession.getMapper(RoleMapper.class);
Role role = rolemapper.getRole(1L);
logger.info(role.getRoleName());
logger.info("使用相同的sqlSession再次获取POJO....");
Role role2 = rolemapper.getRole(1L);
logger.info(role2.getRoleName());
}finally{
if(sqlSession != null){
sqlSession.close();
}
}
}
}
结果如下:
DEBUG 2018-05-28 18:57:13,653 org.apache.ibatis.logging.LogFactory: Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
INFO 2018-05-28 18:57:13,713 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 初始化参数:【{prop1=value1}】
DEBUG 2018-05-28 18:57:13,738 org.apache.ibatis.datasource.pooled.PooledDataSource: PooledDataSource forcefully closed/removed all connections.
DEBUG 2018-05-28 18:57:13,738 org.apache.ibatis.datasource.pooled.PooledDataSource: PooledDataSource forcefully closed/removed all connections.
DEBUG 2018-05-28 18:57:13,738 org.apache.ibatis.datasource.pooled.PooledDataSource: PooledDataSource forcefully closed/removed all connections.
DEBUG 2018-05-28 18:57:13,738 org.apache.ibatis.datasource.pooled.PooledDataSource: PooledDataSource forcefully closed/removed all connections.
INFO 2018-05-28 18:57:13,747 com.learn.ssn.chapter4.databaseidprovider.MyDataBaseIdProvider: {msg=自定义DatabaseIdProvider}
DEBUG 2018-05-28 18:57:13,929 org.apache.ibatis.datasource.pooled.PooledDataSource: Created connection 896681694.
DEBUG 2018-05-28 18:57:14,008 org.apache.ibatis.transaction.jdbc.JdbcTransaction: Opening JDBC Connection
DEBUG 2018-05-28 18:57:14,017 org.apache.ibatis.datasource.pooled.PooledDataSource: Created connection 226710952.
DEBUG 2018-05-28 18:57:14,017 org.apache.ibatis.transaction.jdbc.JdbcTransaction: Setting autocommit to false on JDBC Connection [com.mysql.jdbc.Connection@d8355a8]
DEBUG 2018-05-28 18:57:14,019 com.learn.ssn.chapter3.mapper.RoleMapper.getRole: ==> Preparing: select id, role_name, note from t_role where id = ?
DEBUG 2018-05-28 18:57:14,037 com.learn.ssn.chapter3.mapper.RoleMapper.getRole: ==> Parameters: 1(Long)
INFO 2018-05-28 18:57:14,049 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 创建对象: []
INFO 2018-05-28 18:57:14,049 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 创建对象: []
INFO 2018-05-28 18:57:14,049 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 是否和上次创建的是同一个对象:[ true]
INFO 2018-05-28 18:57:14,050 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 创建对象: com.learn.ssn.chapter3.pojo.Role@7cd62f43
INFO 2018-05-28 18:57:14,050 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 创建对象: com.learn.ssn.chapter3.pojo.Role@7cd62f43
INFO 2018-05-28 18:57:14,050 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 是否和上次创建的是同一个对象:[ true]
DEBUG 2018-05-28 18:57:14,051 com.learn.ssn.chapter3.mapper.RoleMapper.getRole: <== Total: 1
INFO 2018-05-28 18:57:14,051 com.learn.ssn.chapter3.main.Chapter3Main:
INFO 2018-05-28 18:57:14,051 com.learn.ssn.chapter3.main.Chapter3Main: 使用相同的sqlSession再次获取POJO....
INFO 2018-05-28 18:57:14,051 com.learn.ssn.chapter3.main.Chapter3Main:
DEBUG 2018-05-28 18:57:14,051 org.apache.ibatis.transaction.jdbc.JdbcTransaction: Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.Connection@d8355a8]
DEBUG 2018-05-28 18:57:14,051 org.apache.ibatis.transaction.jdbc.JdbcTransaction: Closing JDBC Connection [com.mysql.jdbc.Connection@d8355a8]
DEBUG 2018-05-28 18:57:14,051 org.apache.ibatis.datasource.pooled.PooledDataSource: Returned connection 226710952 to pool.
可以看到,虽然对同一个sql进行了两次获取,但是只是执行了一次,因为代码是使用了同一个SqlSession对象获取的。当第一次通过SQL和参数获取对象后,SqlSession会把它缓存起来,如果下次的SQL和参数都没有发生变化,并且缓存没有超过时间或者声明需要刷新时,它就会从缓存中获取数据。
然后我们把上述代码修改成如下所示:
package com.learn.ssn.chapter3.main;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import com.learn.ssn.chapter3.mapper.RoleMapper;
import com.learn.ssn.chapter3.pojo.Role;
import com.learn.ssn.chapter3.utils.SqlSessionFactoryUtils;
public class Chapter3Main {
public static void main(String[] args) {
Logger logger = Logger.getLogger(Chapter3Main.class);
SqlSession sqlSession = null;
SqlSession sqlSession2 = null;
try{
sqlSession = SqlSessionFactoryUtils.openSqlSession();
RoleMapper rolemapper = sqlSession.getMapper(RoleMapper.class);
Role role = rolemapper.getRole(1L);
logger.info(role.getRoleName());
sqlSession.commit();
logger.info("使用不同的sqlSession再次获取POJO....");
sqlSession2 = SqlSessionFactoryUtils.openSqlSession();
RoleMapper rolemapper2 = sqlSession2.getMapper(RoleMapper.class);
Role role2 = rolemapper2.getRole(1L);
logger.info(role2.getRoleName());
sqlSession2.commit();
}finally{
if(sqlSession != null){
sqlSession.close();
}
}
}
}
结果如下:
DEBUG 2018-05-28 19:04:56,390 org.apache.ibatis.logging.LogFactory: Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
INFO 2018-05-28 19:04:56,440 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 初始化参数:【{prop1=value1}】
DEBUG 2018-05-28 19:04:56,457 org.apache.ibatis.datasource.pooled.PooledDataSource: PooledDataSource forcefully closed/removed all connections.
DEBUG 2018-05-28 19:04:56,457 org.apache.ibatis.datasource.pooled.PooledDataSource: PooledDataSource forcefully closed/removed all connections.
DEBUG 2018-05-28 19:04:56,457 org.apache.ibatis.datasource.pooled.PooledDataSource: PooledDataSource forcefully closed/removed all connections.
DEBUG 2018-05-28 19:04:56,457 org.apache.ibatis.datasource.pooled.PooledDataSource: PooledDataSource forcefully closed/removed all connections.
INFO 2018-05-28 19:04:56,459 com.learn.ssn.chapter4.databaseidprovider.MyDataBaseIdProvider: {msg=自定义DatabaseIdProvider}
DEBUG 2018-05-28 19:04:56,632 org.apache.ibatis.datasource.pooled.PooledDataSource: Created connection 896681694.
DEBUG 2018-05-28 19:04:56,714 org.apache.ibatis.transaction.jdbc.JdbcTransaction: Opening JDBC Connection
DEBUG 2018-05-28 19:04:56,721 org.apache.ibatis.datasource.pooled.PooledDataSource: Created connection 226710952.
DEBUG 2018-05-28 19:04:56,721 org.apache.ibatis.transaction.jdbc.JdbcTransaction: Setting autocommit to false on JDBC Connection [com.mysql.jdbc.Connection@d8355a8]
DEBUG 2018-05-28 19:04:56,723 com.learn.ssn.chapter3.mapper.RoleMapper.getRole: ==> Preparing: select id, role_name, note from t_role where id = ?
DEBUG 2018-05-28 19:04:56,751 com.learn.ssn.chapter3.mapper.RoleMapper.getRole: ==> Parameters: 1(Long)
INFO 2018-05-28 19:04:56,761 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 创建对象: []
INFO 2018-05-28 19:04:56,761 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 创建对象: []
INFO 2018-05-28 19:04:56,761 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 是否和上次创建的是同一个对象:[ true]
INFO 2018-05-28 19:04:56,767 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 创建对象: com.learn.ssn.chapter3.pojo.Role@7cd62f43
INFO 2018-05-28 19:04:56,767 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 创建对象: com.learn.ssn.chapter3.pojo.Role@7cd62f43
INFO 2018-05-28 19:04:56,767 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 是否和上次创建的是同一个对象:[ true]
DEBUG 2018-05-28 19:04:56,767 com.learn.ssn.chapter3.mapper.RoleMapper.getRole: <== Total: 1
INFO 2018-05-28 19:04:56,768 com.learn.ssn.chapter3.main.Chapter3Main:
INFO 2018-05-28 19:04:56,768 com.learn.ssn.chapter3.main.Chapter3Main: 使用不同的sqlSession再次获取POJO....
DEBUG 2018-05-28 19:04:56,768 org.apache.ibatis.transaction.jdbc.JdbcTransaction: Opening JDBC Connection
DEBUG 2018-05-28 19:04:56,777 org.apache.ibatis.datasource.pooled.PooledDataSource: Created connection 60559178.
DEBUG 2018-05-28 19:04:56,777 org.apache.ibatis.transaction.jdbc.JdbcTransaction: Setting autocommit to false on JDBC Connection [com.mysql.jdbc.Connection@39c0f4a]
DEBUG 2018-05-28 19:04:56,777 com.learn.ssn.chapter3.mapper.RoleMapper.getRole: ==> Preparing: select id, role_name, note from t_role where id = ?
DEBUG 2018-05-28 19:04:56,778 com.learn.ssn.chapter3.mapper.RoleMapper.getRole: ==> Parameters: 1(Long)
INFO 2018-05-28 19:04:56,778 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 创建对象: []
INFO 2018-05-28 19:04:56,778 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 创建对象: []
INFO 2018-05-28 19:04:56,778 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 是否和上次创建的是同一个对象:[ true]
INFO 2018-05-28 19:04:56,778 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 创建对象: com.learn.ssn.chapter3.pojo.Role@42e26948
INFO 2018-05-28 19:04:56,778 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 创建对象: com.learn.ssn.chapter3.pojo.Role@42e26948
INFO 2018-05-28 19:04:56,778 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 是否和上次创建的是同一个对象:[ true]
DEBUG 2018-05-28 19:04:56,778 com.learn.ssn.chapter3.mapper.RoleMapper.getRole: <== Total: 1
INFO 2018-05-28 19:04:56,778 com.learn.ssn.chapter3.main.Chapter3Main:
DEBUG 2018-05-28 19:04:56,779 org.apache.ibatis.transaction.jdbc.JdbcTransaction: Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.Connection@d8355a8]
DEBUG 2018-05-28 19:04:56,779 org.apache.ibatis.transaction.jdbc.JdbcTransaction: Closing JDBC Connection [com.mysql.jdbc.Connection@d8355a8]
DEBUG 2018-05-28 19:04:56,779 org.apache.ibatis.datasource.pooled.PooledDataSource: Returned connection 226710952 to pool.
注意,commit()方法的使用,如果不进行commit,是不会有一级缓存的。
可以看到sql的确是执行了两次,这说明了一级缓存是存在SqlSession层面的,对于不同的SqlSession对象是不能共享的.
二级缓存
为了使SqlSession对象之间可以共享相同的缓存,有时候需要开启二级缓存,开启 方法也很简单,
1. 在映射文件中添加 <cache />
2. POJO中实现 java.io.Serializable接口
配置如下所示:
映射文件:
<?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="com.learn.ssn.chapter3.mapper.RoleMapper">
<resultMap id="roleMap" type="role">
<id property="id" column="id" />
<result property="roleName" column="role_name" />
<result property="note" column="note" />
</resultMap>
<sql id="roleCols">
id, role_name, note
</sql>
<cache />
<insert id="insertRole" parameterType="role">
insert into t_role (role_name, note) values ( #{roleName}, #{note})
</insert>
<delete id="deleteRole" parameterType="long">
delete from t_role where id = #{id}
</delete>
<update id="updateRole" parameterType="role">
update t_role set role_name = #{roleName}, note = #{note} where id = #{id}
</update>
<select id="getRole" parameterType="role" resultType="role">
select <include refid="roleCols" /> from t_role where id = #{id}
</select>
<select id="findRoles" parameterType="string" resultType="role">
select id, role_name as roleName, note from t_role
where role_name like concat('%', #{roleName}, '%' )
</select>
</mapper>
POJO如下:
package com.learn.ssn.chapter3.pojo;
import java.io.Serializable;
public class Role implements Serializable {
private Long id;
private String roleName;
private String note;
public long getId(){
return id;
}
public void setId(long id){
this.id = id;
}
public String getRoleName(){
return roleName;
}
public void setRoleName(String roleName){
this.roleName = roleName;
}
public String getNote(){
return note;
}
public void setNote(String note){
this.note = note;
}
}
主函数和上述一致仍然是role和role2,测试结果如下:
DEBUG 2018-05-28 19:10:09,745 org.apache.ibatis.logging.LogFactory: Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
INFO 2018-05-28 19:10:09,804 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 初始化参数:【{prop1=value1}】
DEBUG 2018-05-28 19:10:09,825 org.apache.ibatis.datasource.pooled.PooledDataSource: PooledDataSource forcefully closed/removed all connections.
DEBUG 2018-05-28 19:10:09,825 org.apache.ibatis.datasource.pooled.PooledDataSource: PooledDataSource forcefully closed/removed all connections.
DEBUG 2018-05-28 19:10:09,825 org.apache.ibatis.datasource.pooled.PooledDataSource: PooledDataSource forcefully closed/removed all connections.
DEBUG 2018-05-28 19:10:09,825 org.apache.ibatis.datasource.pooled.PooledDataSource: PooledDataSource forcefully closed/removed all connections.
INFO 2018-05-28 19:10:09,827 com.learn.ssn.chapter4.databaseidprovider.MyDataBaseIdProvider: {msg=自定义DatabaseIdProvider}
DEBUG 2018-05-28 19:10:10,008 org.apache.ibatis.datasource.pooled.PooledDataSource: Created connection 896681694.
DEBUG 2018-05-28 19:10:10,080 com.learn.ssn.chapter3.mapper.RoleMapper: Cache Hit Ratio [com.learn.ssn.chapter3.mapper.RoleMapper]: 0.0
DEBUG 2018-05-28 19:10:10,084 org.apache.ibatis.transaction.jdbc.JdbcTransaction: Opening JDBC Connection
DEBUG 2018-05-28 19:10:10,091 org.apache.ibatis.datasource.pooled.PooledDataSource: Created connection 1047503754.
DEBUG 2018-05-28 19:10:10,091 org.apache.ibatis.transaction.jdbc.JdbcTransaction: Setting autocommit to false on JDBC Connection [com.mysql.jdbc.Connection@3e6fa38a]
DEBUG 2018-05-28 19:10:10,092 com.learn.ssn.chapter3.mapper.RoleMapper.getRole: ==> Preparing: select id, role_name, note from t_role where id = ?
DEBUG 2018-05-28 19:10:10,109 com.learn.ssn.chapter3.mapper.RoleMapper.getRole: ==> Parameters: 1(Long)
INFO 2018-05-28 19:10:10,123 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 创建对象: []
INFO 2018-05-28 19:10:10,123 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 创建对象: []
INFO 2018-05-28 19:10:10,123 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 是否和上次创建的是同一个对象:[ true]
INFO 2018-05-28 19:10:10,124 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 创建对象: com.learn.ssn.chapter3.pojo.Role@e25b2fe
INFO 2018-05-28 19:10:10,124 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 创建对象: com.learn.ssn.chapter3.pojo.Role@e25b2fe
INFO 2018-05-28 19:10:10,124 com.learn.ssn.chapter4.objectfactory.MyObjectFactory: 是否和上次创建的是同一个对象:[ true]
DEBUG 2018-05-28 19:10:10,125 com.learn.ssn.chapter3.mapper.RoleMapper.getRole: <== Total: 1
INFO 2018-05-28 19:10:10,125 com.learn.ssn.chapter3.main.Chapter3Main:
INFO 2018-05-28 19:10:10,133 com.learn.ssn.chapter3.main.Chapter3Main: 使用不同的sqlSession再次获取POJO....
DEBUG 2018-05-28 19:10:10,170 com.learn.ssn.chapter3.mapper.RoleMapper: Cache Hit Ratio [com.learn.ssn.chapter3.mapper.RoleMapper]: 0.5
INFO 2018-05-28 19:10:10,170 com.learn.ssn.chapter3.main.Chapter3Main:
DEBUG 2018-05-28 19:10:10,170 org.apache.ibatis.transaction.jdbc.JdbcTransaction: Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.Connection@3e6fa38a]
DEBUG 2018-05-28 19:10:10,170 org.apache.ibatis.transaction.jdbc.JdbcTransaction: Closing JDBC Connection [com.mysql.jdbc.Connection@3e6fa38a]
DEBUG 2018-05-28 19:10:10,170 org.apache.ibatis.datasource.pooled.PooledDataSource: Returned connection 1047503754 to pool.
可以看到,不同的SqlSession在获取同一条记录,都只是发送过一次SQL获取数据。因为这个时候Mybatis将其保存在SqlSessionFactory中,可以提供给各个SqlSession使用,只是它需要一个序列化和反序列化的过程而已,所以需要实现Serializable接口。
好了,一个简单的关于Mybatis的例子,如果需要具体的参数配置,还需要好好研读了。