day11
Mybatis中的缓存
缓存作用
- 作用: 提高程序运行效率
- 物理说明: 一般保存在内存中, 缓存数据一般是数据库数据
- 在查询相同数据时, 不去再次查询数据库, 而是选择查询缓存
一级缓存
定义: 可以直接使用的缓存
Mybatis为了提高查询效率, 启动一级缓存
Mybatis默认条件下只开启一级缓存, 一级缓存是sqlSession级别的, 在同一个sqlSession中查询数据可以共享数据.
一级缓存测试
第一次查询会查询数据库, 后两次查询则查询缓存
java测试代码:
//一级缓存测试
@Test
public void test01(){
SqlSession sqlSession = sqlSessionFactory.openSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
//第一次查询会查询数据库
List<Emp> empList = mapper.selecetEmp();
//后两次查询查询缓存
List<Emp> empList2 = mapper.selecetEmp();
List<Emp> empList3 = mapper.selecetEmp();
}
运行截图:
只有一次查询
修改表之后再次查询
测试代码:
//一级缓存保护性测试
@Test
public void test02(){
SqlSession sqlSession = sqlSessionFactory.openSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
List<Emp> empList = mapper.selectEmp();
Emp emp = new Emp(null, "Uzi", 12);
int rows = mapper.insertEmp(emp);
List<Emp> empList2 = mapper.selectEmp();
}
如果数据库中的数据被修改, 则第二次查询会查询数据库, 保证数据有效性
特点:
一级缓存默认sqlSession级别.在同一个sqlSession内共享数据, 单线程操作
二级缓存
需配置一些配置才可以使用的缓存
说明: Mybatis针对多线程操作查询数据库, 研发了二级缓存, 可以提升查询效率
解释: 由同一个SqlSessionFactory产生SqlSession共享数据
开关情况: 默认情况下,二级缓存关闭, 需要手动开启
常识: 二级缓存, 对象必须序列化
java测试代码:
//二级缓存测试
@Test
public void test03(){
SqlSession sqlSession1 = sqlSessionFactory.openSession();
EmpMapper mapper1 = sqlSession1.getMapper(EmpMapper.class);
List<Emp> empList1 = mapper1.selectEmp();
sqlSession1.close();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
EmpMapper mapper2=sqlSession2.getMapper(EmpMapper.class);
List<Emp> empList2 = mapper2.selectEmp();
}
实现序列化接口
序列化代码:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Emp implements Serializable {
private Integer empId;
private String empName;
private Integer empAge;
}
开启二级缓存
二级缓存是根据当前Mapper决定的, 针对Mapper开启,所以写在mapper.xml文件中
测试说明:
由于测试问题, 在同一个测试方法中, 程序无法区分两个线程, 所以需要手动关闭线程
Mybatis缓存应用场景
一级缓存只适用于同一个sqlSession
二级缓存只应用于同一个服务器
当用户访问不同服务器进行查询时, 二级缓存就显得有些鸡肋
实际开发中, 用户更多的使用第三方缓存, 一级缓存和二级缓存业务上很少使用
缓存的中的数据一般都是热点数据, 普通基本的数据依然查询数据库 所以一般都是第三方缓存配合 一级-二级 缓存 共同使用
第三方缓存主要解决多个服务器共享数据的问题
引入jar包
<!-- Mybatis EHCache整合包 -->
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.2.1</version>
</dependency>
<!-- slf4j日志门面的一个具体实现 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
编写ehcache.xml配置文件
<?xml version="1.0" encoding="utf-8" ?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<!-- 磁盘保存路径 -->
<diskStore path="D:\atguigu\ehcache"/>
<defaultCache
maxElementsInMemory="1000"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>
<!--
属性说明:
diskStore:指定数据在磁盘中的存储位置。
defaultCache:当借助CacheManager.add("demoCache")创建Cache时,EhCache便会采用<defalutCache/>指定的的管理策略
以下属性是必须的:
maxElementsInMemory - 在内存中缓存的element的最大数目
maxElementsOnDisk - 在磁盘上缓存的element的最大数目,若是0表示无穷大
eternal - 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断
overflowToDisk - 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上
以下属性是可选的:
timeToIdleSeconds - 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大
timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大
diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区.
diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。
diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每隔120s,相应的线程会进行一次EhCache中数据的清理工作
memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)
-->
配置Cache标签
<!--使用第三方二级缓存-->
<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>
逆向工程
逆向工程介绍
一般用户使用mybatis的常规操作都是固定的,CURD, 如果所有的代码都是有规律的, 则完全可以通过代码自动实现
- Mapper接口
- Mapper映射文件
- POJO实体对象
- 基本CURD接口方法-sql文件等语法
上述操作都可以使用采用逆向工程实现
逆向工程案例
引入插件
向pom.xml中写入插件
<!-- 控制Maven在构建过程中相关配置 -->
<build>
<!-- 构建过程中用到的插件 -->
<plugins>
<!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.0</version>
<!--允许覆盖原始数据-->
<configuration>
<overwrite>true</overwrite>
</configuration>
<!-- 插件的依赖 -->
<dependencies>
<!-- 逆向工程的核心依赖 -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.2</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.2</version>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
编辑generatorConfig.xml的配置文件
注意要修改代码中的配置
- 数据库名
- 用户名和密码
- 导入的代码块选择
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--
targetRuntime: 执行生成的逆向工程的版本
MyBatis3Simple: 生成基本的CRUD(清新简洁版)
MyBatis3: 生成带条件的CRUD(奢华尊享版)
-->
<context id="DB2Tables" targetRuntime="MyBatis3">
<commentGenerator>
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!-- 数据库的连接信息 -->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC&allowMultiQueries=true&rewriteBatchedStatements=true&characterEncoding=utf-8"
userId="root"
password="buzai555">
<property name="nullCatalogMeansCurrent" value="true"/>
</jdbcConnection>
<!-- javaBean的生成策略-->
<javaModelGenerator targetPackage="com.atguigu.mybatis.bean" targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- SQL映射文件的生成策略 -->
<sqlMapGenerator targetPackage="com.atguigu.mybatis.mapper" targetProject=".\src\main\resources">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<!-- Mapper接口的生成策略 -->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.atguigu.mybatis.mapper" targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!-- 逆向分析的表 -->
<!-- tableName设置为%号,可以对应所有表,此时不写domainObjectName -->
<!-- domainObjectName属性指定生成出来的实体类的类名 -->
<!-- <table tableName="user" domainObjectName="User"/>-->
<table tableName="%"/>
</context>
</generatorConfiguration>
导入操作
以上操作完成后要在Maven中进行导入操作
Mybatis分页插件
分页规则
分页插件用法
引入jar包
<!-- 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.0</version>
</dependency>
引入配置
在Mybatis中引入配置代码
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
在PageHelper.startPage 后写需要分页的查询代码