首先创建项目,这里就不使用Spring框架了,直接用mybatis原生:
准备工作
首先创建maven项目,引入依赖:
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
创建我们的实体类:
public class Blog {
private String name;
private Integer id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
@Override
public String toString() {
return "Blog{" +
"name='" + name + '\'' +
", id=" + id +
'}';
}
}
配置我们的mybtais 的配置文件 mybatis-config.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>
<settings>
<!--全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存。 -->
<setting name="cacheEnabled" value="true" />
<setting name="useGeneratedKeys" value="true" />
<setting name="defaultExecutorType" value="REUSE" />
<setting name="logImpl" value="STDOUT_LOGGING" />
</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/bank?serverTimezone=GMT%2B8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/learning/BlogMapper.xml"/>
</mappers>
</configuration>
我们要在数据库里面有配置好该实体类对应的表:
创建Mapper类 BlogMapper
:
public interface BlogMapper {
public Blog selectBlog(Integer id);
}
创建其对应的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.learning.mapper.BlogMapper">
<select id="selectBlog" resultType="com.learning.Blog" flushCache="false">
select * from Blog where id = #{id}
</select>
</mapper>
还有一个类:
public class MyBatisConfig {
public static SqlSessionFactory getSqlSessionFactory(){
String resource = "com/learning/mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
return sqlSessionFactory;
}
}
此时目录结构如下:
上面是准备工作,接下来测试一级缓存和二级缓存
一级缓存:
public class Starter {
public static void main(String[] args) {
SqlSessionFactory sqlSessionFactory = MyBatisConfig.getSqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Blog blog1 = mapper.selectBlog(1);
System.out.println("blog1的值是"+blog1);
blog1.setName("修改成我设置的值");
System.out.println("=============开始同一个 Sqlsession 的第二次查询============");
Blog blog2 = mapper.selectBlog(1);
System.out.println("blog2的值是"+blog2);
System.out.println("判断blog1和blog2对象是否相等"+blog1.equals(blog2));
sqlSession.close();
}
}
运行之后如下:
可以发现,第二次拿到的值就是第一次拿到的对象。
如果我们这两次查询使用的是不同的SqlSession,如下:
public static void main(String[] args) {
SqlSessionFactory sqlSessionFactory = MyBatisConfig.getSqlSessionFactory();
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
BlogMapper blogMapper1 = sqlSession1.getMapper(BlogMapper.class);
BlogMapper blogMapper2 = sqlSession2.getMapper(BlogMapper.class);
Blog blog1 = blogMapper1.selectBlog(1);
Blog blog2 = blogMapper2.selectBlog(2);
System.out.println("判断两个对象是否相等: "+blog1.equals(blog2));
sqlSession1.close();
sqlSession2.close();
}
使用上面的代码进行执行:
发现两个对象不相等,说明一级缓存只作用于同一个SqlSeesion
一级缓存是SqlSession级别的缓存。在操作数据库时需要构造 sqlSession对象,一级缓存的作用域是同一个SqlSession,在同一个sqlSession中两次执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。当一个sqlSession结束后该sqlSession中的一级缓存也就不存在了。一级缓存是默认开启
的
二级缓存
二级缓存不是默认开启的。我们要使用二级缓存需要去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.learning.mapper.BlogMapper">
<select id="selectBlog" resultType="com.learning.Blog" flushCache="false">
select * from Blog where id = #{id}
</select>
<cache readOnly="true"></cache>
</mapper>
如上,使用 <cache readOnly="true"></cache>
开启二级缓存,然后还要给实体类实现序列化接口:
public class Blog implements Serializable {
private static final long serialVersionUID = -7946444982033976955L;
。。。
}
执行如下代码:
public static void main(String[] args) {
SqlSessionFactory sqlSessionFactory = MyBatisConfig.getSqlSessionFactory();
SqlSession session = sqlSessionFactory.openSession();
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog1 = mapper.selectBlog(1);
System.out.println(blog1);
System.out.println("第二次执行");
Blog blog2 = mapper.selectBlog(1);
System.out.println(blog2);
session.commit();
System.out.println("二级缓存观测点");
SqlSession session2 = sqlSessionFactory.openSession();
BlogMapper mapper2 = session2.getMapper(BlogMapper.class);
Blog blog3 = mapper2.selectBlog(1);
System.out.println(blog3);
System.out.println("第二次执行");
Blog blog4 = mapper2.selectBlog(1);
System.out.println(blog4);
session2.commit();
System.out.println(blog1==blog2);
}
使用debug方式执行:
发现blog1和blog2 的引用相同,但是blog3和blog4的引用并不同。
原因: 因为blog2是从一级缓存中取出的,所以和blog1 的值相同,在sqlsession1 使用了commit()方法之后,该对象被序列化到二级缓存中了,blog3是从二级缓存中反序列化得到的对象,blog4也是反序列化得到的对象,得到的不是原实例,而是原实例的拷贝
而且观察控制台可以发现,我们的select语句只查询了一次:
所以二级缓存产生了效果