MyBatis基础使用五
MyBatis缓存(了解即可,现在主流的缓存通过redis)
MyBatis的一级缓存
一级缓存是SqlSession级别的,通过同一个SqlSession查阅的数据会被缓存,下次查阅相同的数据,就会从缓存中直接获取,不会从数据库重新访问
一级缓存失效的四种情况:
- 不同的SqlSession对应不同的一级缓存
- 同一个SqlSession但是查阅条件不同
- 同一个SqlSession两次查阅期间执行了任何一次增删改操作(执行增删改操作会清空缓存)
- 同一个SqlSession两次查阅期间手动清空了缓存(SqlSession.clearcache())
MyBatis的二级缓存
二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取
二级缓存开启的条件:
- 在核心配置文件中,设置全局属性cacheEnable="true",默认为true,不需要设置
- 在映射文件中设置
标签 - 二级缓存必须在SqlSession关闭或提交之后有效
- 查询的数据所转换的实体类类型必须实现序列化的接口
二级缓存失效的情况:
- 两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效
二级缓存的相关配置
在mapper配置文件中添加的cache标签可以设置一些属性:
- eviction属性:缓存huishoucelue,默认的是LRU。
LRU(Least Recently Used) --最近最少使用的:移除最长时间不被使用的对象。
FIFO(First In First Out)--先进先出:按对象进入缓存的顺序来移除它们。
SOFT---软引用:移除基于垃圾回收器状态和软引用规则的对象。
WEAK--弱引用:更积极的移除基于垃圾收集器状态和弱引用规则的对象。
- flushInterval属性:刷新间隔,单位毫秒
默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新
- size属性:引用数目,正整数
代表缓存最多可以储存多少个对象,太大容易导致内存溢出
- readOnly属性:只读,true/false
true:只读缓存——会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这还提供了很重要的性能优势。
false:读写缓存——会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。
MyBaits缓存查询的顺序
先查询二级缓存,因为二级缓存中可能会有已经查出来的数据,可以拿来直接使用。
如果二级缓存没用命中,再查询一级缓存
如果一级缓存没用命中,再查询数据库
SqlSession关闭之后,一级缓存中的数据会写入二级缓存
整合第三方缓存EHCache
首先添加项目依赖
<!-- Mybatis EHCache整合包-->
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.2.2</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="http://ehcache.org/ehcache.xsd"
updateCheck="false">
<!-- 磁盘保存路径-->
<diskStore path="D:\Mybatis\ehcache"/>
<defaultCache
eternal="false"
maxElementsInMemory="10000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="259200"
memoryStoreEvictionPolicy="LRU"/>
<cache
name="cloud_user"
eternal="false"
maxElementsInMemory="5000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="1800"
memoryStoreEvictionPolicy="LRU"/>
</ehcache>
EHCache的配置说明
<!--EHCache配置说明
- defaultCache:默认缓存策略,当ehcache找不到定义的缓存时,则使用这个缓存策略。只能定义一个。
- name:缓存名称。
- maxElementsInMemory:缓存最大数目
- maxElementsOnDisk:硬盘最大缓存个数。
- eternal:对象是否永久有效,一但设置了,timeout将不起作用。
- overflowToDisk:是否保存到磁盘,当系统宕机时
- timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
- timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
- diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
- diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
- diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
- memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
- clearOnFlush:内存数量最大时是否清除。
- memoryStoreEvictionPolicy:可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。
- FIFO,first in first out,这个是大家最熟的,先进先出。
- LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。
- LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。
设置二级缓存的类型
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
加入logback日志
存在SLF4时,作为简易的log4j将失效,此时我们需要借助SLF4J的具体实现来打印日志。创建logback的配置文件logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="log_home" value="logs/wfy" />
<!-- 控制台输出 -->
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n</pattern>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log_home}/boss.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 按天回滚 daily -->
<fileNamePattern>${log_home}/boss.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 30天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{80} - %msg%n</pattern>
</encoder>
</appender>
<!-- 用户访问日志输出 -->
<appender name="SYS-USER" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log_home}/sys-user.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 按天回滚 daily -->
<fileNamePattern>${log_home}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{80} - %msg%n</pattern>
</encoder>
</appender>
<!-- 显示形成的sql、使用的参数、结果集 -->
<!--
<logger name="java.sql" level="debug" />
<logger name="org.springframework.jdbc" level="debug" />
-->
<logger name="com.wfy.mapper" level="info" />
<root level="info">
<appender-ref ref="stdout" />
<appender-ref ref="file" />
</root>
<!--系统用户操作日志-->
<logger name="sys-user" level="info">
<appender-ref ref="SYS-USER"/>
</logger>
</configuration>
MyBatis逆向工程
概念:在使用mybatis时需要程序员自己编写sql语句,针对单表的sql语句量是很大的,mybatis官方提供了一种根据数据库表生成mybatis执行代码的工具,这个工具就是一个逆向工程。
配置逆向工程
一、配置项目依赖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.wfy</groupId>
<artifactId>mybatis-07-mbg</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!-- mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.11</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!--log4j日志-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>
</dependencies>
<!--控制Maven在构建过程中相关配置-->
<build>
<!--构建过程中用到的插件-->
<plugins>
<!--具体插件,逆向工程的操作是以构建过程中插件形式出现的-->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.0</version>
<!--插件的依赖-->
<dependencies>
<!-- 逆向工程的核心依赖-->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.0</version>
</dependency>
<!--MYSQL驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
二、配置映射文件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:生成基本的CURD(清新简洁版)
MyBatis3:生成带条件的CURD(奢华尊享版)
-->
<context id="MysqlTables" targetRuntime="MyBatis3">
<commentGenerator>
<property name="suppressDate" value="true"/>
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!-- jdbc链接信息 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/ssm"
userId="root" password="root">
</jdbcConnection>
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!-- 生成POJO类的位置 -->
<javaModelGenerator targetPackage="com.wfy.pojo"
targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!-- mapper映射文件生成的位置 -->
<sqlMapGenerator targetPackage="com.wfy.mapper"
targetProject="src/main/resources">
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!-- mapper接口生成的位置 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.wfy.mapper"
targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!-- 指定要生成的表 -->
<table tableName="emp" domainObjectName="Emp">
<!-- <property name="useActualColumnNames" value="true"/>-->
<!-- <generatedKey column="id" sqlStatement="Mysql" identity="true"/>-->
</table>
<table tableName="dept" domainObjectName="Dept"></table>
</context>
</generatorConfiguration>
逆向工程有两个版本:一种是简洁版本(只生成基本的CURD),另一种是完整版本(生成带条件的CRUD)
分页插件实现分页功能
基本的分页功能的实现(旧版)
我们只得到sql中存在limit的指令可以进行分页查询的操作
select * from emp limit (0,5)
这就表示首页显示五条数据
0:表示的是index,当前页的起始索引
5:表示的是pageSize,每页显示的条数
我们从页面上可以获取pageNum(当前页的页码),还有pageSize(每页显示的条数)。由此我们就可以算出index(当前页的起始索引),从而获取数据。
index=(pageNum-1)*pageSize
使用分页插件实现分页查询的功能
一、导入项目依赖pom.xml
<!-- 分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.0</version>
</dependency>
二、创建核心配置文件
<plugins>
<!--配置分页插件-->
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
三、测试展示案例
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wfy.mapper.EmpMapper;
import com.wfy.pojo.Emp;
import com.wfy.utils.SqlSessionFactoryUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class PageTest {
/**分页查询获取到的数据
* PageInfo{pageNum=1, pageSize=4, size=4, startRow=1, endRow=4, total=30, pages=8,
* list=Page{count=true, pageNum=1, pageSize=4, startRow=0, endRow=4, total=30, pages=8, reasonable=false, pageSizeZero=false}
* [Emp{empId=8, empName='张三', age=20, gender='男'},
* Emp{empId=9, empName='李四', age=21, gender='男'},
* Emp{empId=10, empName='王五', age=22, gender='女'},
* Emp{empId=11, empName='', age=null, gender='null'}],
* prePage=0, nextPage=2, isFirstPage=true, isLastPage=false, hasPreviousPage=false,
* hasNextPage=true, navigatePages=8, navigateFirstPage=1, navigateLastPage=8,
* navigatepageNums=[1, 2, 3, 4, 5, 6, 7, 8]}
*
*
*/
@Test
public void pageTest(){
SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
//查询功能之前开启分页功能
Page<Object> page = PageHelper.startPage(1, 4);
List<Emp> emps = mapper.SelectAll();
//查询功能之后可以获取分页相关的所有数据
PageInfo<Emp> pages= new PageInfo<>(emps);
emps.forEach(System.out::println);
//System.out.println(page);
System.out.println(pages);
}
}
标签:缓存,false,基础,二级缓存,mybatis,SqlSession,使用,MyBatis,import From: https://www.cnblogs.com/wfy-studying/p/16814803.html查询的分页功能获取的数据中的属性的意思:
- pageNum: 当前页的页码
- pageSize: 每页显示的条数
- size: 当前页显示的真实条数
- total: 总记录数
- pages: 总页数
- prePage: 上一页的页码
- nextPage: 下一页的页码
- isFirstPage/isLastPage: 是否为第一页/最后一页
- hasPreviousPage/hasNextPage: 是否存在上一页/下一页
- navigatePages: 导航分页的页码数
- navigatepageNums: 导航分页的页码,[1,2,3,4,5]