MyBatis学习(四)

MyBatis的缓存

MyBatis的一级缓存

一级缓存是SqlSession级别的,通过同一个SqlSeesion查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库访问
使一级缓存失效的四种情况:

  1. 不同的SqlSession对应不同的一级缓存
  2. 同一个SqlSession但是查询条件不同
  3. 同一个SqlSession两次查询期间执行了任何一次增删改操作
  4. 同一个SqlSession两次查询期间手动清空了缓存
/**
     * 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);

MyBatis的二级缓存

二级缓存是SqlSeesionFactory级别,通过同一个SqlSeesionFactory创建的SqlSeesion查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取
二级缓存开启的条件
a>在核心配置文件中,设置全局配置属性cacheEnabled=“true”,默认true,不需要设置
b>在映射文件中设置标签
c>二级缓存必须在SqlSession关闭或提交之后有效
d>查询的数据所转换的实体类类型必须实现序列化的接口
使二级缓存失效的四种情况:

两次查询之间执行了任意的增删改,会使一级缓存和二级缓存同时失效

在这里插入图片描述
MyBatis学习(四)_第1张图片
在这里插入图片描述

MyBatis二级缓存相关的配置和缓存查询的顺序

相关配置
在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包功能
MyBatis学习(四)_第2张图片
创建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>

配置文件说明
MyBatis学习(四)_第3张图片
设置二级缓存的类型

<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是支持正向工程的
逆向工程:先创建数据库表,由框架负责根据数据库表,反向生成如下资源:

  • Java实体类
  • Mapper接口
  • Mapper映射文件

创建逆向工程的-简洁版

<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>

MyBatis学习(四)_第4张图片
MyBatis学习(四)_第5张图片

创建逆向工程的-豪华版

创建区别只是将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

意思意思得了

你可能感兴趣的:(笔记,mybatis,学习,缓存)