目的:使用Redis做MyBatis的二级缓存提高查询速度
参考文献:
https://blog.csdn.net/xushiyu1996818/article/details/89215428
https://blog.51cto.com/zhengqidaxia/1960256
步骤小结
- 导入依赖
- mybatis-config.xml中开启缓存
- 在Mapper.xml中设置二级缓存
- 其他(其他文件的编写)
- 测试
1、创建一个空的Maven项目.
略
目录结构如下
2、导入依赖.
<properties>
<spring.version>5.2.7.RELEASE</spring.version>
</properties>
<dependencies>
<!-- mybatis-redis cache实现 -->
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-redis</artifactId>
<version>1.0.0-beta2</version>
</dependency>
<!-- redis -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>2.3.4.RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.1.0</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<!-- mybatis整合spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.5</version>
</dependency>
<!-- 连接池 druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.23</version>
</dependency>
<!-- mysql-connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
<scope>runtime</scope>
</dependency>
<!-- springmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- lombok 需要安装插件 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
<!-- test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.11.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.11.2</version>
</dependency>
</dependencies>
3、几个配置文件内容.
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="logImpl" value="LOG4J"/>-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
<!-- 开启驼峰和下滑线的命名转换 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 开启缓存 必须 同时 在 mapper.xml 使用缓存 -->
<setting name="cacheEnabled" value="true"/>
</settings>
</configuration>
spring-mybatis.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 1.关联数据库配置文件 配置文件名为 db.properties -->
<!-- <context:property-placeholder location="classpath:db.properties"/>-->
<!-- 2.配置数据源 -->
<!-- druid -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!-- 基本属性 url、user、password-->
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<!-- 配置初始化大小、最小、最大-->
<property name="maxActive" value="20" />
<property name="initialSize" value="1" />
<property name="minIdle" value="1" />
<!-- 配置获取连接等待超时的时间-->
<property name="maxWait" value="60000" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒-->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒-->
<property name="minEvictableIdleTimeMillis" value="300000" />
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<!-- 打开PSCache,并且指定每个连接上、PSCache的大小-->
<property name="poolPreparedStatements" value="true" />
<property name="maxOpenPreparedStatements" value="20" />
<!-- 配置监控统计拦截的filters,去掉后监控界面sql无法统计-->
<property name="filters" value="stat" />
</bean>
<!-- 3.sqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- <bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">-->
<property name="dataSource" ref="dataSource"/>
<!-- 绑定mybatis-config.xml 文件 -->
<property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/>
<!-- 绑定 com.liuyou.blog.***Mapper.xml 取代mybatis-config.xml中的<mapper>标签作用 -->
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
<!-- 指定别名 -->
<property name="typeAliasesPackage" value="pojo"/>
</bean>
<!-- 4.配置dao(mapper)接口扫描,即Mapper扫描器,动态的实现了Dao接口可以注入到spring容器中 == 代替了实现类 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--注入 sqlSessionFactory-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!-- 要扫描的dao包 -->
<property name="basePackage" value="mapper"/>
</bean>
</beans>
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 加载配置文件 -->
<!-- <context:property-placeholder location="classpath:*.properties"/>-->
<!-- 加载配置文件 -->
<context:property-placeholder location="classpath:db.properties,redis.properties"/>
<!-- 导入spring配置文件 -->
<import resource="classpath:spring/spring-mybatis.xml"/>
</beans>
db.properties
# 驱动
jdbc.driver=com.mysql.jdbc.Driver
# url 数据库 为 liuyou_blog 可自行修改
jdbc.url=jdbc:mysql://localhost:3306/ssmbuild?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
# 用户名
jdbc.username=root
# 密码
jdbc.password=mysql
redis.properties
必须保证 配置文件名是
redis.properties
,以及其内容中key满足org.mybatis.caches.redis.RedisConfig
属性名对应(包含其父类的属性名)
#redis的服务器地址 ip地址
host=...
#redis的服务端口
port=6379
#链接数据库
database=0
#redis验证密码 没有就不用配置
password=
#客户端超时时间单位是毫秒
connectionTimeout=10000
#最大连接数
maxTotal=100
#最大空闲数
maxIdle=20
#最小空闲数
minIdle=1
#最大建立连接等待时间
maxWaitMills=2000
#指明是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
testOnBorrow=true
#当调用return Object方法时,进行有效性检查
testOnReturn=true
4、实体类、Mapper接口及Mapper.xml.
Books
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Books implements Serializable {
private static final long serialVersionUID = -4420834025097707421L;
private Integer bookID;
private String bookName;
private Integer bookCounts;
private String detail;
}
BooksMapper
public interface BooksMapper {
//add a book
int addBook(Books books);
//delete a book
int deleteBookById(int id);
//update a book
int updateBook(Books books);
//queryAll
List<Books> queryAll();
}
BooksMapper.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="mapper.BooksMapper">
<!--在当前Mapper.xml中使用二级缓存-->
<!--
eviction LRU(默认) 缓存淘汰策略
LRU – 最近最少使用的:移除最长时间不被使用的对象。
FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
flushInterval 缓存时间,以毫秒为单位,默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。
size 缓存大小,每个缓存可以存储 1024(默认) 个列表或对象的引用
readOnly 是否是只读的,只读的缓存会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存会返回缓存对象的拷贝(通过序列化) 。这会慢一些,但是安全,因此默认是false。
-->
<cache eviction="LRU"
type="org.mybatis.caches.redis.RedisCache"
flushInterval="120000"
size="1024"
readOnly="true"/>
<!--
useCache表示是否需要使用缓存
flushCache表示插入后是否需要刷新缓存
以下是默认情况:
<select ... flushCache="false" useCache="true"/>
<insert ... flushCache="true"/>
<update ... flushCache="true"/>
<delete ... flushCache="true"/>
-->
<insert id="addBook" parameterType="Books">
insert into ssmbuild.books(bookName, bookCounts, detail)
value(#{bookName},#{bookCounts},#{detail});
</insert>
<delete id="deleteBookById" parameterType="int">
delete from ssmbuild.books where bookID = #{bookID};
</delete>
<update id="updateBook" parameterType="Books">
update ssmbuild.books
set bookName = #{bookName},
bookCounts = #{bookCounts},
detail = #{detail}
where bookID=#{bookID};
</update>
<select id="queryAll" resultType="books">
select *
from books;
</select>
</mapper>
5、测试及结果.
测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestMyBatis {
@Autowired
BooksMapper booksMapper;
@Test
public void test(){
System.out.println("=======================start===========================");
System.out.println("查询所有的书籍: ");
System.out.println("first"+booksMapper.queryAll());
System.out.println("再次查询所有的书籍: Redis做二级缓存");
System.out.println("second"+booksMapper.queryAll());
System.out.println("========================end==========================");
}
}
结果
第一次查询,缓存命中率:0,没命中缓存,从数据库中拿数据
第二次查询,缓存命中率:0.5,命中缓存,从缓存中拿数据
=======================start===========================
查询所有的书籍:
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1722011b] was not registered for synchronization because synchronization is not active
Cache Hit Ratio [mapper.BooksMapper]: 0.0 // 第一次,缓存命中率 0
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@352c1b98] will not be managed by Spring
==> Preparing: select * from books; // 执行sql语句
==> Parameters:
<== Columns: bookID, bookName, bookCounts, detail
<== Row: 74, test-spring-mybatis, 10, spring整合mybatis
<== Total: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1722011b]
first[Books(bookID=74, bookName=test-spring-mybatis, bookCounts=10, detail=spring整合mybatis)] // 查询结果(从数据库中获取)
再次查询所有的书籍: Redis做二级缓存
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@ae3540e] was not registered for synchronization because synchronization is not active
Cache Hit Ratio [mapper.BooksMapper]: 0.5 // 第二次,缓存命中率 0.5(以命中)
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@ae3540e]
second[Books(bookID=74, bookName=test-spring-mybatis, bookCounts=10, detail=spring整合mybatis)] // 查询结果(从缓存中获取)
========================end==========================
扩展.
RedisConfig所有属性(含父类).
host = ""
port = 6379
connectionTimeout = 10000
soTimeout = 2000
password = ""
database = 0
clientName = null
maxTotal = 100
maxIdle = 20
minIdle = 1
lifo = true
fairness = false
maxWaitMillis = -1
minEvictableIdleTimeMillis = 60000
evictorShutdownTimeoutMillis = 10000
softMinEvictableIdleTimeMillis = -1
numTestsPerEvictionRun = -1
evictionPolicy = null
evictionPolicyClassName = "org.apache.commons.pool2.impl.DefaultEvictionPolicy"
testOnCreate = false
testOnBorrow = true
testOnReturn = true
testWhileIdle = true
timeBetweenEvictionRunsMillis = 30000
blockWhenExhausted = true
jmxEnabled = true
jmxNamePrefix = "pool"
jmxNameBase = null