Mybatis一级缓存
项目结构

缓存的概念
什么是缓存?
存在于内存中的临时数据.
为什么使用缓存?
减少和数据库的交互次数, 提供执行效率.
什么样的数据使用缓存, 什么样的数据不能使用缓存?
适用于缓存:
经常查询并且不经常改变的.
数据的正确与否对最终结果影响不大的.
不适用于缓存:
经常改变的数据
数据的正确与否对最终结影响很大的.
列如: 商品的库存, 银行的汇率, 故事的牌价.
Mybatis中的一级缓存和二级缓存
一级缓存:
它只的是Mybatis中SqlSession对象的缓存.
当我们执行查询之后, 查询的结果会同时存入到SqlSession为我们提供一块区域中.
该区域的结构是一个Map. 当我们再次查询同样的数据, mybatis会先去SqlSession
中查询是否有, 有的话直接拿出来用.
当SqlSession对象消失时, mybatis的以及缓存也就消失了.
二级缓存:
它指的是Mybatis中SqlSessionFactory对象的缓存.
由同一个SqlSessionFactory对象创建的SqlSession共享其缓存
二级缓存的使用步骤:
第一步: 让Mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)
第二步: 让当前的映射文件支持二级缓存(在userDao.xml中配置)
第三步: 让当前的操作支持二级缓存(在select标签中配置)
一级缓存的存在
一级缓存是 SqlSession 级别的缓存,只要 SqlSession 没有 flush 或 close,它就存在。
配置文件
-
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.xiaoge</groupId> <artifactId>cache</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.5</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.13</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies> </project> -
jdbcConfig.properties
jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/eesy_mybatis jdbc.username=root jdbc.password=123456 -
SqlMapConfig.xml
<?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> <!--配置properties--> <properties resource="jdbcConfig.properties"> </properties> <!-- 使用typeAliases配置别名, 它只能配置domain中类的别名 --> <typeAliases> <package name="com.xiaoge.domain"></package> </typeAliases> <!--配置环境--> <environments default="mysql"> <!--配置mysql环境--> <environment id="mysql"> <!--配置事务--> <transactionManager type="JDBC"></transactionManager> <!--配置连接池--> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </dataSource> </environment> </environments> <mappers> <package name="com.xiaoge.dao"></package> </mappers> </configuration> -
UserDao.xml
<?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.xiaoge.dao.UserDao"> <!-- 查询所有用户操作 --> <select id="findAll" resultType="user"> select * from user </select> <!--查询条记录信息--> <select id="findById" parameterType="java.lang.Integer" resultType="user"> select * from user where id = #{userId} </select> <!-- 修改用户信息 --> <update id="updateUser" parameterType="user"> update user set username = #{username}, address = #{address} where id = #{id} </update> </mapper>
实体类
-
User
package com.xiaoge.domain; import java.util.Date; /** * @Author: 潇哥 * @DateTime: 2020/3/4 下午4:03 * @Description: TODO */ public class User { private Integer id; private String username; private String address; private String sex; private Date birthday; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } }
持久层接口
-
UserDao
package com.xiaoge.dao; import com.xiaoge.domain.User; import java.util.List; /** * @Author: 潇哥 * @DateTime: 2020/3/4 下午4:19 * @Description: 用户的持久层接口 */ public interface UserDao { /** * 查询所有用户, 同时获取到用户下所有账户的信息 * @return */ public List<User> findAll(); /** * 获取用户信息 * @return */ public User findById(Integer id); /** * 修改用户信息 * @param user */ public void updateUser(User user); }
测试持久层接口方法
-
UserTest
package com.xiaoge.test; import com.xiaoge.dao.UserDao; import com.xiaoge.domain.User; 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 org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.io.InputStream; /** * @Author: 潇哥 * @DateTime: 2020/3/16 下午6:12 * @Description: TODO */ public class UserTest { private SqlSession sqlSession; private UserDao userDao; private InputStream is; private SqlSessionFactory factory; @Before public void init() throws IOException { is = Resources.getResourceAsStream("SqlMapConfig.xml"); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); factory = builder.build(is); sqlSession = factory.openSession(); userDao = sqlSession.getMapper(UserDao.class); } @After public void destroy() throws IOException { if (is != null) { is.close(); } } /** * 测试一级缓存 */ @Test public void findFirstLevelCacheTest(){ User user1 = userDao.findById(41); System.out.println(user1); // 清除缓存, 清除SqlSession的一级缓存 sqlSession.clearCache(); userDao = sqlSession.getMapper(UserDao.class); User user2 = userDao.findById(41); System.out.println(user2); System.out.println(user1 == user2); // 运行结果 2020-03-18 14:56:18,876 1492 [ main] DEBUG om.xiaoge.dao.UserDao.findById - ==> Preparing: select * from user where id = ? // 这里 2020-03-18 14:56:18,948 1564 [ main] DEBUG om.xiaoge.dao.UserDao.findById - ==> Parameters: 41(Integer) 2020-03-18 14:56:18,990 1606 [ main] DEBUG om.xiaoge.dao.UserDao.findById - <== Total: 1 com.xiaoge.domain.User@f2ff811 2020-03-18 14:56:18,992 1608 [ main] DEBUG om.xiaoge.dao.UserDao.findById - ==> Preparing: select * from user where id = ? // 这里 2020-03-18 14:56:18,993 1609 [ main] DEBUG om.xiaoge.dao.UserDao.findById - ==> Parameters: 41(Integer) 2020-03-18 14:56:18,994 1610 [ main] DEBUG om.xiaoge.dao.UserDao.findById - <== Total: 1 com.xiaoge.domain.User@50caa560 false // 这里 // 很明显查询了两次, 因为我们清除了一级缓存 // clearCache() 清除缓存 // 也可以用close() 然后再次创建一个SqlSession对象 } /** * 测试一级缓存2 */ @Test public void findFirstLevelCacheTest2(){ User user1 = userDao.findById(41); System.out.println(user1); User user2 = userDao.findById(41); System.out.println(user2); System.out.println(user1 == user2); // 运行结果 2020-03-18 14:58:28,342 1470 [ main] DEBUG om.xiaoge.dao.UserDao.findById - ==> Preparing: select * from user where id = ? // 这里 2020-03-18 14:58:28,420 1548 [ main] DEBUG om.xiaoge.dao.UserDao.findById - ==> Parameters: 41(Integer) 2020-03-18 14:58:28,470 1598 [ main] DEBUG om.xiaoge.dao.UserDao.findById - <== Total: 1 com.xiaoge.domain.User@f2ff811 com.xiaoge.domain.User@f2ff811 true // 这里 // 很明显是拿的缓存, 没有去数据库拿数据 } /** * 测试缓存的同步 */ @Test public void clearCacheTest(){ User user1 = userDao.findById(41); System.out.println(user1); user1.setUsername("update user clear cache"); user1.setAddress("北京市海定区"); // 更新用户信息 userDao.updateUser(user1); User user2 = userDao.findById(41); System.out.println(user2); System.out.println(user1 == user2); // 运行结果 2020-03-18 15:10:37,702 1861 [ main] DEBUG om.xiaoge.dao.UserDao.findById - ==> Preparing: select * from user where id = ? // 这里 2020-03-18 15:10:37,825 1984 [ main] DEBUG om.xiaoge.dao.UserDao.findById - ==> Parameters: 41(Integer) 2020-03-18 15:10:37,870 2029 [ main] DEBUG om.xiaoge.dao.UserDao.findById - <== Total: 1 com.xiaoge.domain.User@f2ff811 2020-03-18 15:10:37,875 2034 [ main] DEBUG .xiaoge.dao.UserDao.updateUser - ==> Preparing: update user set username = ?, address = ? where id = ? 2020-03-18 15:10:37,876 2035 [ main] DEBUG .xiaoge.dao.UserDao.updateUser - ==> Parameters: update user clear cache(String), 北京市海定区(String), 41(Integer) 2020-03-18 15:10:37,879 2038 [ main] DEBUG .xiaoge.dao.UserDao.updateUser - <== Updates: 1 2020-03-18 15:10:37,879 2038 [ main] DEBUG om.xiaoge.dao.UserDao.findById - ==> Preparing: select * from user where id = ? // 这里 2020-03-18 15:10:37,879 2038 [ main] DEBUG om.xiaoge.dao.UserDao.findById - ==> Parameters: 41(Integer) 2020-03-18 15:10:37,882 2041 [ main] DEBUG om.xiaoge.dao.UserDao.findById - <== Total: 1 com.xiaoge.domain.User@2a266d09 false // 这里 } }
一级缓存的分析
一级缓存是 SqlSession 范围的缓存,当调用 SqlSession 的修改,添加,删除,commit(),close()等
浙公网安备 33010602011771号