緩存:
- 存在記憶體中的臨時資料。
- 将使用者經常查詢的資料放在緩存中,再次查詢時無需通路磁盤,提高效率。解決高并發問題。
- 可以減少IO。
-
經常查詢且不常改變的資料适合使用緩存。
(注意:讀資料才走緩存)
Mybatis緩存
官方文檔:
https://mybatis.org/mybatis-3/zh/sqlmap-xml.html
- Mybatis有着非常強大的緩存特性,可以非常友善地定制和配置緩存。
-
Mybatis中定義了兩級緩存:一級緩存和二級緩存
一級緩存:預設情況下一級。SqlSession級别,也稱為本地緩存。
二級緩存: 需要手動開啟和配置,namespace級别
- 自定義緩存:Mybatis定義了緩存接口Cache,可以通過實作Cache接口來自定義二級緩存。
Cache接口實作類
示例
獲得SqlSession的工具類,openSession為true時自動送出事務
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.IOException;
import java.io.InputStream;
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
String resource = "mybatis-config.xml";
try {
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession() {
SqlSession sqlSession = sqlSessionFactory.openSession(true); //自動送出事務
return sqlSession;
}
}
UserMapper接口
import org.apache.ibatis.annotations.Param;
public interface UserMapper {
//根據id查詢使用者
User queryUserById(@Param("id") int id);
//修改使用者
int updateUser(User user);
}
xml配置檔案
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jacob.dao.UserMapper">
<select id="queryUserById" parameterType="_int" resultType="user">
select * from user where user = #{id}
</select>
<update id="updateUser" parameterType="user">
update user set pwd=#{pwd} where user=#{user}
</update>
</mapper>
測試類MyTest
- 一級緩存
import com.jacob.dao.UserMapper;
import com.jacob.pojo.User;
import com.jacob.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
public class MyTest {
@Test
public void test() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.queryUserById(1);
User user1 = mapper.queryUserById(1); //隻查詢一次
System.out.println(user == user1); //從緩存拿到user1, true
sqlSession1.close();
}
}
增删改可能會改變原來資料, 是以會重新整理緩存
public class MyTest {
@Test
public void test() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.queryUserById(1);
mapper.updateUser(new User(4, "jj", "14")); //重新整理了緩存
User user1 = mapper.queryUserById(1); //查詢第二次
System.out.println(user == user1); //false
sqlSession1.close();
}
}
執行結果如下:
利用sqlSession.clearCache()清理緩存
public class MyTest {
@Test
public void test() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.queryUserById(1);
sqlSession.clearCache(); //清理緩存
User user1 = mapper.queryUserById(1); //查詢第二次
System.out.println(user == user1); //false
sqlSession1.close();
}
}
-
二級緩存
namespace級别
工作機制:- 一個會話查詢一條資料,資料會存放在目前會話的一級緩存中
- 若目前會話關閉,這個會話的一級緩存消失, 開啟二級緩存後,一級緩存的資料儲存至二級緩存
- 新的會話可在二級緩存擷取資料
在Mapper中開啟
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jacob.dao.UserMapper">
<cache readOnly="true"/>
<select id="queryUserById" parameterType="_int" resultType="user" useCache="true">
select * from user where user = #{id}
</select>
<update id="updateUser" parameterType="user">
update user set pwd=#{pwd} where user=#{user}
</update>
</mapper>
public class MyTest {
@Test
public void test() {
//兩個 sqlSession
SqlSession sqlSession = MybatisUtils.getSqlSession();
SqlSession sqlSession1 = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
User user = mapper.queryUserById(1);
sqlSession.close(); //sqlSession關閉了資料進入二級緩存
User user1 = mapper1.queryUserById(1);
System.out.println(user == user1); //從緩存拿到user1, true
sqlSession1.close();
}
}
若sqlSession 後關閉,查詢了兩次
public class MyTest {
@Test
public void test() {
//兩個 sqlSession
SqlSession sqlSession = MybatisUtils.getSqlSession();
SqlSession sqlSession1 = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
User user = mapper.queryUserById(1);
User user1 = mapper1.queryUserById(1);
System.out.println(user == user1); //false, sqlSession未關閉,二級緩存中沒有資料,不同sqlSession,一級緩存不同
sqlSession.close();
sqlSession1.close();
}
}
查詢了兩次
- 緩存原理(來自狂神說Java)