一级缓存是SqlSession级别的,通过同一个SqlSeesion查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库访问
使一级缓存失效的四种情况:
/**
* MyBatis的一级缓存:
* MyBatis的一级缓存是SqlSeesion级别的,即通过同一个SqlSession查询的数据将会被缓存
* 再次使用同一个SqlSession查询的同一条数据,会从缓存中获取
* 使一级缓存失效的四种情况:
* 1) 不同的SqlSession对应不同的一级缓存
* 2) 同一个SqlSession但是查询条件不同
* 3) 同一个SqlSession两次查询期间执行了任何一次增删改操作
* 4) 同一个SqlSession两次查询期间手动清空了缓存
*/
CacheMapper mapper = sqlSession.getMapper(CacheMapper.class);
Emp emp1 = mapper.getEmpById(1);
System.out.println(emp1);
Emp emp2 = mapper.getEmpById(1);
System.out.println(emp2);
上面的执行结果将只查询了一次,说明使用了缓存,不过不同的SqlSeesion对象不会有使用缓存
SqlSession sqlSession1 = SqlsessionUtil.getSqlSession();
CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class);
Emp emp1 = mapper1.getEmpById(1);
System.out.println(emp1);
sqlSession1.clearCache();//清空一级缓存
//mapper1.insertEmp(new Emp(null,"小红",25,"男"));
Emp emp2 = mapper1.getEmpById(1);
System.out.println(emp2);
二级缓存是SqlSeesionFactory级别,通过同一个SqlSeesionFactory创建的SqlSeesion查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取
二级缓存开启的条件
a>在核心配置文件中,设置全局配置属性cacheEnabled=“true”,默认true,不需要设置
b>在映射文件中设置标签
c>二级缓存必须在SqlSession关闭或提交之后有效
d>查询的数据所转换的实体类类型必须实现序列化的接口
使二级缓存失效的四种情况:
两次查询之间执行了任意的增删改,会使一级缓存和二级缓存同时失效
相关配置
在mapper配置文件中添加cache标签可以设置一些属性
①eviction属性:缓存回收策略,默认是LRU
LRU(Least Recently Used)-最近最少使用的:移除最长时间不被使用的对象。
FIFO(First in First out)-先进先出:按对象进入缓存的顺序来移除它们
SOFT-软引用:移除基于垃圾回收器状态和软引用规则的对象
WEAK-弱引用:更积极地移除基于垃圾回收器状态和弱引用规则的对象
②flushInteval属性:刷新间隔,单位毫秒
默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新
③size属性:引用数目,正整数
代表缓存最多可以存储多少个对象,太大容易导致内存溢出
④readOnly属性:只读,true/flase
true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能别修改。这提供了很重要的性能优势
false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false
缓存查询的顺序
先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用
如果二级缓存没有命中,再查询一级缓存
如果一级缓存也没有命中,则查询数据库
SqlSession关闭后,一级缓存中的数据会写入二级缓存
一级缓存的清理缓存方法不会清除二级缓存,并且第三方缓存是针对二级缓存的,二级缓存可以使用第三方缓存
<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>
各Jar包功能
创建EHCache的配置文件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日志
存在SLF4J时,作为简易日志的log4j将失效,此时我们需要借助SLF4J的具体实现logback来打印日
志。 创建logback的配置文件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>
测试
@Test
public void testCache()throws IOException {
InputStream is =Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession1 = sqlSessionFactory.openSession(true);
CacheMapper mapper1 = sqlSession1.getMapper(CacheMapper.class);
Emp emp1 = mapper1.getEmpById(1);
System.out.println(emp1);
sqlSession1.close();
SqlSession sqlSession2 = sqlSessionFactory.openSession(true);
CacheMapper mapper2 = sqlSession2.getMapper(CacheMapper.class);
Emp emp2 = mapper2.getEmpById(1);
System.out.println(emp2);
sqlSession2.close();
}
这次是使用的二级缓存,没有再次查询
正向工程:先创建Java实体类,由框架负责根据实体类生成数据表。Hibernate是支持正向工程的
逆向工程:先创建数据库表,由框架负责根据数据库表,反向生成如下资源:
<packaging>jarpackaging>
<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>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.16version>
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>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.16version>
dependency>
dependencies>
plugin>
plugins>
build>
创建区别只是将Simple去掉
@Test
public void testMBG(){
SqlSession sqlSession = SqlsessionUtil.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
//根据id查询数据
// Emp emp = mapper.selectByPrimaryKey(1);
// System.out.println(emp);
//查询所有数据
// List list = mapper.selectByExample(null);
// list.forEach(System.out::println);
//根据条件查询
// EmpExample empExample = new EmpExample();
// empExample.createCriteria().andEmpNameEqualTo("张三").andAgeGreaterThanOrEqualTo(20);
// empExample.or().andGenderEqualTo("男");
// List emps = mapper.selectByExample(empExample);
// emps.forEach(System.out::println);
Emp emp = new Emp(1,"小黑",null,"女");
//测试普通修改功能
//mapper.updateByPrimaryKey(emp);
//测试选择性修改
mapper.updateByPrimaryKeySelective(emp);
}
limt index pageSize
pageSize:每页显示的条数
pageNum:当前页的页码
index:当前页的起始索引,index=(pageNum-1)*pageSize
count:总记录数
totalPage:总页数
totalPage = count / pageSize
if(count % pageSize != 0 ){
totalPage +=1;
}
pageSize = 4 pageNum = 1 index = 0 limit 0,4
pageSize = 4 pageNum = 3 index = 8 limit 8,4
pageSize = 4 pageNum = 6 index = 20 limit 8,4
添加依赖
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>5.2.0version>
dependency>
配置分页插件
在MyBatis的核心配置文件中配置插件
@Test
public void testPage(){
SqlSession sqlSession = SqlsessionUtil.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
//查询功能之前开启分页功能
PageHelper.startPage(1,4);
List<Emp> list = mapper.selectByExample(null);
list.forEach(System.out::println);
}
获取相关数据
@Test
public void testPage(){
SqlSession sqlSession = SqlsessionUtil.getSqlSession();
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
//查询功能之前开启分页功能
Page<Object> page = PageHelper.startPage(1, 4);
List<Emp> list = mapper.selectByExample(null);
//在查询功能之后可以获取分页相关的所有数据
PageInfo<Emp>pageInfo = new PageInfo<>(list,5);
list.forEach(System.out::println);
System.out.println(page);
}
Emp{empId=1, empName='AAA', age=null, gender='null', deptId=null}
Emp{empId=2, empName='a', age=null, gender='null', deptId=null}
Emp{empId=3, empName='a', age=null, gender='null', deptId=null}
Emp{empId=4, empName='a', age=null, gender='null', deptId=null}
Page{count=true, pageNum=1, pageSize=4, startRow=0, endRow=4, total=30, pages=8, reasonable=false, pageSizeZero=false}[Emp{empId=1, empName='AAA', age=null, gender='null', deptId=null}, Emp{empId=2, empName='a', age=null, gender='null', deptId=null}, Emp{empId=3, empName='a', age=null, gender='null', deptId=null}, Emp{empId=4, empName='a', age=null, gender='null', deptId=null}]
Process finished with exit code 0
意思意思得了