• 【MyBatis】五、MyBatis的缓存机制与逆向工程


    MyBatis的缓存机制

    MyBatis的一级缓存

    MyBatis的一级缓存是默认开启的,是基于SqlSession级别的缓存,也就是说,只要是同一个sqlSession,只要执行的语句相同,则不会去数据库中进行查找,而是会从缓存中找到对应的结果。

    MyBatis一级缓存失效的四种情况

    • 使用了不同的sqlsession对象
    • 同一个sqlsession对象,但查询条件不同
    • 两次查询之间进行了增删改操作(增删改操作会清空缓存)
    • 手动清空缓存(sqlsession.clearCache())

    MyBatis二级缓存

    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>
      
      • 1
      • 2
      • 3
      • 4
      • 5
    • 对应的实体类必须序列化

      public class Emp implements Serializable {
      
      • 1

    注意:只有在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);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    注意:在两次查询之间进行了增删改操作的话,会使缓存失效

    手动清空缓存不会清空二级缓存

    二级缓存的相关信息

    • eviction属性:缓存回收策略

      • LRU(默认):最近最少使用策略
      • FIFO:先进先出
      • SOFT-软引用:移除基于垃圾回收器状态和软引用规则的对象
      • WEAK-弱引用:更积极的移除基于垃圾回收器状态和弱引用规则的对象
    • flushInterval属性:刷新间隔(二级缓存的清空间隔)

      默认为不刷新,只在进行了增删改之后刷新。

    • size属性:引用数目,正整数

      代表缓存中可以存储多少个对象,不要设置太大,容易造成内存溢出

    • readOnly属性:默认为false

      • true:缓存返回的对象为只读缓存,其会给调用者返回缓存对象相同的实例,因此这些对象不能修改,这提供了很大的性能优势
      • false:缓存返回的对象为读写缓存(通过序列化),这会慢一些但是保证了数据的安全性。

    MyBatis的缓存查询顺序

    • 先查询二级缓存,因为二级缓存中可能会存在其他程序已经查询出来的数据,其可以直接拿来使用。
    • 如果二级缓存没有命中,会去查询一级缓存(还未提交到二级缓存的数据可能会存在于这里)
    • 如果一级缓存也没有命中,查询数据库
    • SqlSession关闭之后,将一级缓存中的内容存储到二级缓存

    MyBatis整合EHCache

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    添加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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    设置二级缓存的类型

    • 在xxxMapper.xml文件中设置二级缓存类型
    <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
    
    • 1

    加入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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    EHCache配置文件说明

    属性名是否必须作用
    maxElementsInMemory在内存中缓存的element的最大数目
    maxElementsOnDisk在磁盘上缓存的element的最大数目,若是0表示无穷大
    eternal设定缓存的elements是否永远不过期。 如果为true,则缓存的数据始终有效, 如果为false那么还要根据timeToIdleSeconds、timeToLiveSeconds判断
    overflowToDisk设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上
    timeToIdleSeconds当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时, 这些数据便会删除,默认值是0,也就是可闲置时间无穷大
    timeToLiveSeconds缓存element的有效生命期,默认是0.,也就是element存活时间无穷大
    diskSpoolBufferSizeMBDiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区
    diskPersistent在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false
    diskExpiryThreadIntervalSeconds磁盘缓存的清理线程运行间隔,默认是120秒。每个120s, 相应的线程会进行一次EhCache中数据的清理工作
    memoryStoreEvictionPolicy当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。 默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出

    MyBatis逆向工程

    引入依赖

    <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    创建mybatis核心配置文件

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    创建逆向工程的配置文件

    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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    之后在右侧的plugins中执行mybatis-generator就可以生成文件了,注意这样会将数据库中的下划线字段映射为驼峰,这样的生成方式只有基础的CRUD功能

    MyBatis逆向工程奢华尊享版

    在高级的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);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    MyBatis分页插件

    配置依赖

            
            <dependency>
                <groupId>com.github.pagehelpergroupId>
                <artifactId>pagehelperartifactId>
                <version>5.2.0version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在mybatis-config中配置分页插件,注意其位置顺序:

    properties、settings、typeAliases、typeHandlers、objectFactory、objectWrapperFactory、reflectorFactory、plugins、environments、databaseIdProvider、mappers

        <plugins>
            <plugin interceptor="com.github.pagehelper.PageInterceptor">plugin>
        plugins>
    
    • 1
    • 2
    • 3

    使用:

        @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);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    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=‘345@qq.com’, 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=‘345@qq.com’, 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]}

  • 相关阅读:
    Python和SQLite游标处理多行数据
    Kafka为什么是高性能高并发高可用架构
    【系统架构设计师】第四章 计算机网络
    【学习笔记】Redis的持久化
    设置TOMCAT SESSIONID 字符长度和生成算法
    【云原生Kubernetes】部署K8S集群架构(admin部署)
    Hbase学习二:Hbase数据特点和架构特点
    R3Live系列学习(四)R2Live源码阅读(2)
    【师兄啊师兄2】大爆料,敖乙回归,创造新里程碑,有望做成年番
    制作一个简单HTML西安旅游网页(HTML+CSS)
  • 原文地址:https://blog.csdn.net/weixin_41365204/article/details/132790522