一、一級緩存和二級緩存
程序中緩存對系統效率的提升是極大的,在Mybatis中,緩存分別爲一級緩存和二級緩存,其中一級緩存是默認開啓的,二級緩存需要手動開啓。
二、一級緩存
說明:
1.Mybatis的一級緩存是默認開啓的。
2.若要停止Mybatis的一級緩存可以通過設置select標籤上的flushCache屬性爲true,會每一次執行完查詢就情況一級緩存。
3.一級緩存的生命週期是一個SqlSession,不能跨SqlSession域
4.該SqlSession下的任何增、刪、改操作都會清空一級緩存
案例
mapepr映射文件
<?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.my.mapper.UserMapper">
<resultMap id="BaseResultMap" type="com.my.entity.User">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="user_name" jdbcType="VARCHAR" property="userName" />
<result column="real_name" jdbcType="VARCHAR" property="realName" />
<result column="sex" jdbcType="CHAR" property="sex" />
<result column="mobile" jdbcType="VARCHAR" property="mobile" />
<result column="email" jdbcType="VARCHAR" property="email" />
<result column="note" jdbcType="VARCHAR" property="note" />
<result column="position_id" jdbcType="INTEGER" property="positionId" />
</resultMap>
<sql id="Base_Column_List">
id, user_name, real_name, sex, mobile, email, note, position_id
</sql>
<!-- flushCache設置爲true則爲關閉一級緩存 -->
<select id="selectById" parameterType="java.lang.Integer" resultMap="BaseResultMap" flushCache="false">
select
<include refid="Base_Column_List" />
from user
where id = #{id,jdbcType=INTEGER}
</select>
<update id="updateByUserSelective" parameterType="com.my.entity.User">
update user
<set>
<if test="userName != null">
user_name = #{userName,jdbcType=VARCHAR},
</if>
<if test="realName != null">
real_name = #{realName,jdbcType=VARCHAR},
</if>
<if test="sex != null">
sex = #{sex,jdbcType=CHAR},
</if>
<if test="mobile != null">
mobile = #{mobile,jdbcType=VARCHAR},
</if>
<if test="email != null">
email = #{email,jdbcType=VARCHAR},
</if>
<if test="note != null">
note = #{note,jdbcType=VARCHAR},
</if>
<if test="positionId != null">
position_id = #{positionId,jdbcType=INTEGER},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
</mapper>
測試代碼:
public class MybatisTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void init() throws IOException {
String resource = "mybatis-config.xml";
//1.使用mybatis的工具讀取配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//2.創建sqlSessionFactory
sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
inputStream.close();
}
/**
* 測試一級緩存,需要通過查看日誌的SQL打印判斷是否緩存
*/
@Test
public void testOneCache() {
//自動提交
SqlSession sqlSession = sqlSessionFactory.openSession(true);
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.selectById(1);
//再次查詢
user = userMapper.selectById(1);
user.setNote("test");
//更新
userMapper.updateByUserSelective(user);
//再次查詢
user = userMapper.selectById(1);
System.out.println(user);
sqlSession.close();
}
/**
* 測試一級緩存跨Session,需要通過查看日誌的SQL打印判斷是否緩存
*/
@Test
public void testOneCacheSession() {
//自動提交
SqlSession sqlSession = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
User user = userMapper.selectById(1);
User user2 = userMapper2.selectById(1);
sqlSession.close();
sqlSession2.close();
}
}
說明:緩存效果不能通過代碼直接看到,需要自己debug查看打印日誌進行觀察。
三、二級緩存
說明:
1.二級緩存默認是不使用的,需要手動添加。
2.二級緩存需要把Mybatis配置文件中的cacheEnabled設爲true(默認是true,但設置後更直觀)。
3.開啓二級緩存後還需要去mapper.xml文件中通過使用cache或cache-ref開啓二級緩存的使用。
4.二級緩存的生命週期是一個SqlSessionFactory(一般一個項目中只用一個)。
5.二級緩存是跨SqlSession的,但是並不跨命名空間(每個mapper.xml)。
6.同一個命名空間下的任意SqlSession的增、刪、改操作都會清空二級緩存。
cache和cache-ref標籤介紹:
cache標籤用在mapper.xml文件中,開啓該命名空間的二級緩存,和cache-ref標籤衝突,常用三個屬性:
1.eviction:緩存策略,一般用FIFO
2.flushInterval:多久清空一次,單位秒
3.size:緩存列表數量
cache-ref標籤用在mapper.xml文件中,和其它命名空間共用一個緩存,和cache標籤衝突,只有一個屬性:
1.namespace:需要其共用緩存的命名空間(該值的命名空間需要開啓二級緩存)
案例:
mapper映射文件:
<?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.my.mapper.PositionMapper">
<!-- 開啓二級緩存,使用默認配置 -->
<cache> </cache>
<!-- 和其它命名空間共用一個緩存 -->
<!-- <cache-ref namespace="命名空間"/>-->
<resultMap id="BaseResultMap" type="com.my.entity.Position">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="posname" jdbcType="VARCHAR" property="posname" />
<result column="note" jdbcType="VARCHAR" property="note" />
</resultMap>
<sql id="Base_Column_List">
id, posname, note
</sql>
<select id="selectById" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from position
where id = #{id,jdbcType=INTEGER}
</select>
<update id="updateByPositionSelective" parameterType="com.my.entity.Position">
update position
<set>
<if test="posname != null">
posname = #{posname,jdbcType=VARCHAR},
</if>
<if test="note != null">
note = #{note,jdbcType=VARCHAR},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
</mapper>
測試代碼:
public class MybatisTest {
private SqlSessionFactory sqlSessionFactory;
@Before
public void init() throws IOException {
String resource = "mybatis-config.xml";
//1.使用mybatis的工具讀取配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//2.創建sqlSessionFactory
sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
inputStream.close();
}
/**
* 測試二級緩存,需要通過查看日誌的SQL打印判斷是否緩存
*/
@Test
public void testTowCache() {
//自動提交
SqlSession sqlSession = sqlSessionFactory.openSession(true);
SqlSession sqlSession2 = sqlSessionFactory.openSession(true);
PositionMapper positionMapper = sqlSession.getMapper(PositionMapper.class);
PositionMapper positionMapper2 = sqlSession2.getMapper(PositionMapper.class);
Position position = positionMapper.selectById(1);
//再次查詢
position = positionMapper.selectById(1);
position.setNote("test");
//更新
positionMapper.updateByPositionSelective(position);
//再次查詢
position = positionMapper.selectById(1);
System.out.println(position);
sqlSession.close();
}
}
說明:緩存效果不能通過代碼直接看到,需要自己debug查看打印日誌進行觀察。
四、補充說明
1.緩存之間執行的順序,二級緩存—一級緩存—數據庫
2.一般不用二級緩存,因爲二級緩存可能會造成髒讀,例如A命名空間開啓了二級緩存,當B命名空間對A命名空間中的表進行修改時,A命名空間的緩存是無法知曉的。