MyBatis的一级缓存是默认开启的,是基于SqlSession级别的缓存,也就是说,只要是同一个sqlSession,只要执行的语句相同,则不会去数据库中进行查找,而是会从缓存中找到对应的结果。
MyBatis的二级缓存是SqlSessionFactory级别的,也就是说,通过同一个SqlSessionFactory创建的SqlSession对象所查询的结果都会被缓存,而在查询时也都会优先从缓存中获取结果。
MyBatis的二级缓存默认是不开启的
在核心配置文件(mybatis-config.xml)中配置属性cacheEnable=“true”,默认为true不用刻意配置
在映射文件中设置标签:
<mapper namespace="com.qinghe.mybatis.mapper.DynamicSQLMapper">
<cache />
<sql id="empColumn">eid, emp_name, age, sex, emailsql>
对应的实体类必须序列化
public class Emp implements Serializable {
注意:只有在sqlSession关闭或提交之后,信息才会被提交到二级缓存中。
@Test
public void testTwoCache() {
try {
// 获取mybatis配置文件的字节输入流
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
// 工厂模式,创建一个创建sqlSession的工厂,(通过刚刚获取到的输入流)
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
// 创建一个sqlSession对象,开启自动提交
SqlSession sqlSession1 = sqlSessionFactory.openSession(true);
CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class);
System.out.println(mapper1.getEmpByEid(1));
// 只有sqlsession关闭或提交之后二级缓存才生效
sqlSession1.commit();
SqlSession sqlSession2 = sqlSessionFactory.openSession(true);
CacheMapper mapper2 = sqlSession2.getMapper(CacheMapper.class);
System.out.println(mapper2.getEmpByEid(1));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
注意:在两次查询之间进行了增删改操作的话,会使缓存失效
手动清空缓存不会清空二级缓存
eviction属性:缓存回收策略
flushInterval属性:刷新间隔(二级缓存的清空间隔)
默认为不刷新,只在进行了增删改之后刷新。
size属性:引用数目,正整数
代表缓存中可以存储多少个对象,不要设置太大,容易造成内存溢出
readOnly属性:默认为false
MyBatis作为持久层框架,其也提供了整合第三方缓存机制的接口,例如可以整合EHCache:
添加依赖:
<dependency>
<groupId>org.mybatis.cachesgroupId>
<artifactId>mybatis-ehcacheartifactId>
<version>1.2.1version>
dependency>
<dependency>
<groupId>ch.qos.logbackgroupId>
<artifactId>logback-classicartifactId>
<version>1.2.3version>
dependency>
添加encache的配置文件:ehcache.xml(文件名固定)
<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>
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
logback.xml
,名字固定,不可改变
<configuration debug="true">
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%npattern>
encoder>
appender>
<root level="DEBUG">
<appender-ref ref="STDOUT" />
root>
<logger name="com.atguigu.crowd.mapper" level="DEBUG"/>
configuration>
属性名 | 是否必须 | 作用 |
---|---|---|
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(先进先出 |
<dependencies>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.7version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
<dependency>
<groupId>com.mysqlgroupId>
<artifactId>mysql-connector-jartifactId>
<version>8.0.32version>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generatorgroupId>
<artifactId>mybatis-generator-maven-pluginartifactId>
<version>1.3.0version>
<dependencies>
<dependency>
<groupId>org.mybatis.generatorgroupId>
<artifactId>mybatis-generator-coreartifactId>
<version>1.3.2version>
dependency>
<dependency>
<groupId>com.mchangegroupId>
<artifactId>c3p0artifactId>
<version>0.9.2version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.27version>
dependency>
dependencies>
plugin>
plugins>
build>
mybatis-config.xml:
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="jdbc.properties"/>
<typeAliases>
<package name="com.qinghe.mybatis.pojo">package>
typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<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="">package>
mappers>
configuration>
generatorConfig.xml(不得改名)
DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="DB2Tables" targetRuntime="MyBatis3Simple">
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatis"
userId="root"
password="123456">
jdbcConnection>
<javaModelGenerator targetPackage="com.qinghe.mybatis.pojo" targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
javaModelGenerator>
<sqlMapGenerator targetPackage="com.qinghe.mybatis.mapper"
targetProject=".\src\main\resources">
<property name="enableSubPackages" value="true" />
sqlMapGenerator>
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.qinghe.mybatis.mapper" targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
javaClientGenerator>
<table tableName="t_emp" domainObjectName="Emp"/>
<table tableName="t_dept" domainObjectName="Dept"/>
context>
generatorConfiguration>
之后在右侧的plugins中执行mybatis-generator就可以生成文件了,注意这样会将数据库中的下划线字段映射为驼峰,这样的生成方式只有基础的CRUD功能
在高级的MyBatis生成文件中,我们会生成类似于Mybatis-plus的sql映射,以以下方式使用:
注意xxxSeletive方法在操作时会不插入值为null的数据
@Test
public void test1() {
try {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
// List list = mapper.selectByExample(null);
// 创建条件
EmpExample example = new EmpExample();
// and条件这样添加
example.createCriteria().andEmpNameEqualTo("张三").andAgeBetween(20, 90);
// or条件这样添加
example.or().andDidIsNotNull();
List<Emp> list = mapper.selectByExample(example);
list.forEach(item -> {
System.out.println(item);
});
} catch (IOException e) {
throw new RuntimeException(e);
}
}
配置依赖
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>5.2.0version>
dependency>
在mybatis-config中配置分页插件,注意其位置顺序:
properties、settings、typeAliases、typeHandlers、objectFactory、objectWrapperFactory、reflectorFactory、plugins、environments、databaseIdProvider、mappers
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">plugin>
plugins>
使用:
@Test
public void testPageHelper() {
try {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
// 开启PageHelper分页
// 可以使用Page对象接收分页,page对象中会存储一些基本信息
Page<Object> page = PageHelper.startPage(3, 2);
List<Emp> list = mapper.selectByExample(null);
// 也可以在这里使用PageInfo对象接收分页信息,这之中有全部的详细信息
// 第二个形参代表导航的数量:......4、5、6、7、8、9......(例如这种就是有五个)
PageInfo<Emp> pageInfo = new PageInfo<>(list, 5);
System.out.println(page);
System.out.println(pageInfo);
/**
* limit index, pageSize
*
*/
} catch (IOException e) {
throw new RuntimeException(e);
}
}
Page对象中的信息:
Page{count=true, pageNum=3, pageSize=2, startRow=4, endRow=6, total=10, pages=5, reasonable=false, pageSizeZero=false}
[Emp{eid=5, empName=‘田七’, age=22, sex=‘男’, email=‘[email protected]’, did=2}, Emp{eid=6, empName=‘a’, age=null, sex=‘null’, email=‘null’, did=null}]
PageInfo对象中的信息:
PageInfo{pageNum=3, pageSize=2, size=2, startRow=5, endRow=6, total=10, pages=5, list=Page{count=true, pageNum=3, pageSize=2, startRow=4, endRow=6, total=10, pages=5, reasonable=false, pageSizeZero=false}
[Emp{eid=5, empName=‘田七’, age=22, sex=‘男’, email=‘[email protected]’, did=2}, Emp{eid=6, empName=‘a’, age=null, sex=‘null’, email=‘null’, did=null}],
prePage=2, nextPage=4, isFirstPage=false, isLastPage=false, hasPreviousPage=true, hasNextPage=true, navigatePages=5, navigateFirstPage=1, navigateLastPage=5, navigatepageNums=[1, 2, 3, 4, 5]}