MyBatis学习笔记——缓存、逆向工程、PageHelper分页

缓存

MyBatis 的缓存级别

MyBatis 提供两种级别的缓存:一级缓存、二级缓存

  • 一级缓存:MyBatis 默认开启一级缓存,一级缓存是 SqlSession 级别的缓存。
  • 二级缓存:需要手动开启和配置,二级缓存是 namespace(映射文件)级别的缓存。

一级缓存

一个 SqlSession 在执行查询语句之后,会将该查询语句的结果保存在本地缓存中,当该 SqlSession 再次执行相同的查询语句时,会直接在缓存中获取查询结果。

一级缓存失效的几种情况:

  1. 不同的 SqlSession 对应不同的一级缓存。
  2. 同一个 SqlSession 但是查询条件不同
  3. 同一个 SqlSession 两次查询期间执行了增删改操作
  4. 同一个 SqlSession 两次查询期间手动清空了缓存sqlSession.clearCache()

二级缓存

二级缓存是映射文件级别的,不论 SqlSession 是否相同,只要 SqlSession 加载的是同一个 Mapper 接口sqlSession.getMapper(EmpMapper.class),则所有 SqlSession 共享缓存数据。

二级缓存又叫全局缓存,默认关闭,需要手动开启,二级缓存在 SqlSession 提交或关闭之后才会生效sqlSession.commit()或sqlSession.close()

二级缓存的实现步骤:

  1. 在 MyBatis 全局配置文件中开启二级缓存<settings><setting name="cacheEnabled" value="true"/></settings>
  2. 在需要使用二级缓存的映射文件中使用<cache/>配置二级缓存。
  3. Bean 类需要实现Serializable接口
  4. 二级缓存在 sqlSession 提交或关闭时生效。

mybatis-config.xml

<!-- 设置 -->
<settings>
    <!--开启二级缓存-->
    <setting name="cacheEnabled" value="true"/>
</settings>

EmpMapper.xml

<mapper namespace="com.mcc.MyBatis.mapper.EmpMapper">
    <!--使用二级缓存-->
    <cache/>
    ...
</mapper>

Emp.java

package com.mcc.MyBatis.bean;

import java.io.Serializable;

public class Emp implements Serializable {
    private Integer id;
    private String eName;
    private Integer age;
    private String sex;
    private Dept dept;  
}

二级缓存的相关属性

在<cache/>标签中
  • eviction="FIFO":缓存回收策略:
    LRU – 最近最少使用的:移除最长时间不被使用的对象。
    FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
    SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
    WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
    默认为 LRU
  • flushInterval:刷新间隔,单位毫秒
    默认情况是不设置,即没有刷新间隔,缓存只在调用语句时被刷新。
  • size:缓存数目,正整数。
    代表缓存最多可以存储多少个对象,太大容易导致内存溢出。
  • readOnly:只读,true/false默认为 false
    true:只读缓存。会给所有调用者返回缓存对象的相同实例,这些对象不能被修改。这提供了很重要的性能优势。
    false:读写缓存。会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全。

在这里插入图片描述

在增删改查标签中
  1. 全局 setting 的 cacheEnable:
    开启二级缓存,一级缓存一直是打开的。

  2. select 标签的 useCache 属性:
    在开启全局二级缓存的情况下,设置本条 select 语句是否使用二级缓存,一级缓存一直是使用的。
    在这里插入图片描述

  3. 增删改查标签的 flushCache 属性:
    增删改默认 flushCache=“true”,语句执行以后,会同时清空一级和二级缓存
    查询默认 flushCache=“false”。

  4. sqlSession.clearCache():只能用来清除一级缓存。

整合第三方缓存

在映射文件中使用<cache type=""/>,实现使用第三方缓存工具管理本映射文件的缓存数据。

以 ehcache 为例:

步骤:

  1. 引入相关 jar 包。
    在这里插入图片描述

  2. 创建 ehcache 配置文件,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">
    <!-- 磁盘保存路径 -->
    <diskStore path="D:\Java\ehcache\temp"/>

    <defaultCache
            maxElementsInMemory="1000"
            maxElementsOnDisk="10000000"
            eternal="false"
            overflowToDisk="true"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
    </defaultCache>
</ehcache>

<!-- 
属性说明:
l diskStore:指定数据在磁盘中的存储位置。
l defaultCache:当借助CacheManager.add("demoCache")创建Cache时,EhCache便会采用<defalutCache/>指定的的管理策略
 
以下属性是必须的:
l maxElementsInMemory - 在内存中缓存的element的最大数目 
l maxElementsOnDisk - 在磁盘上缓存的element的最大数目,若是0表示无穷大
l eternal - 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断
l overflowToDisk - 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上
 
以下属性是可选的:
l timeToIdleSeconds - 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大
l timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大
 diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区.
l diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。
l diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每个120s,相应的线程会进行一次EhCache中数据的清理工作
l memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)
-->
  1. 在核心配置文件已经开启二级缓存的条件下,在映射文件中使用<cache type=""/>,指定要使用的第三方缓存类的全类名,即<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

逆向工程

介绍

MyBatis Generator:简称 MBG,是一个专门为 MyBatis 框架使用者定制的代码生成器,可以快速的根据表生成对应的映射文件,接口,以及 bean 类。 支持基本的增删改查,以及 QBC 风格的条件查询。但是表连接、存储过程等这些复杂 sql 的定义需要我们手工编写。

官方文档地址

官方工程地址

mbg 配置文件

(1)导入 jar 包:mybatis-generator-core-x.x.x.jar。
(2)mbg-config.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>

    <context id="DB2Tables" targetRuntime="MyBatis3">
        <!--设置数据库连接信息-->
        <jdbcConnection
            driverClass="com.mysql.cj.jdbc.Driver"
            connectionURL="jdbc:mysql://localhost:3306/ssm?serverTimezone=UTC&amp;rewriteBatchedStatements=true&amp;allowMultiQueries=true"
            userId="root"
            password="macheng_0213">
        </jdbcConnection>

        <javaTypeResolver >
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>

        <!--javaBean的生成策略-->
        <javaModelGenerator targetPackage="com.mcc.mbg.pojo" targetProject=".\src">
            <property name="enableSubPackages" value="true" />
            <property name="trimStrings" value="true" />
        </javaModelGenerator>

        <!--映射文件的生成策略-->
        <sqlMapGenerator targetPackage="com.mcc.mbg.mapper"  targetProject=".\conf">
            <property name="enableSubPackages" value="true" />
        </sqlMapGenerator>

        <!--Mapper接口的生成策略-->
        <javaClientGenerator type="XMLMAPPER" targetPackage="com.mcc.mbg.mapper"  targetProject=".\src">
            <property name="enableSubPackages" value="true" />
        </javaClientGenerator>

        <!--设置将数据库中的哪张表对应生成哪个JavaBean-->
        <table tableName="employee" domainObjectName="Emp" />
        <table tableName="department" domainObjectName="Dept" />

    </context>
</generatorConfiguration>

(3)测试。

package com.mcc.mbg.generator;

import org.junit.Test;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;

import java.io.File;
import java.util.ArrayList;

public class Generator {
    @Test
    public void generatorXML() throws Exception {
        ArrayList<String> warnings = new ArrayList<String>();
        boolean overwrite = true;
        File configFile = new File("./conf/mbg-config.xml");
        ConfigurationParser parser = new ConfigurationParser(warnings);
        Configuration config = parser.parseConfiguration(configFile);
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
        myBatisGenerator.generate(null);
    }
}

在这里插入图片描述
在这里插入图片描述
生成的 javaBean、映射文件、Mapper接口。
在这里插入图片描述

Example、Criteria 条件查询

使用 targetRuntime="MyBatis3Simple" 时,生成的是简单的 sql 语句;使用 targetRuntime="MyBatis3" 时,在 JavaBean 中会额外生成 XxxExample.java 类,该类可以支持带条件的查询操作,即 QBC 风格的条件查询。
在这里插入图片描述
QBC 条件查询演示:

package com.mcc.mbg.test;

import com.mcc.mbg.mapper.EmpMapper;
import com.mcc.mbg.pojo.Emp;
import com.mcc.mbg.pojo.EmpExample;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.InputStream;
import java.util.List;

public class TestGenerator {
    @Test
    public void testGeneratorXml() throws Exception {
        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        SqlSession sqlSession = factory.openSession(true);
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);

        //创建Example对象,该对象用于创建Criteria对象
        EmpExample empExample = new EmpExample();
        EmpExample.Criteria c1 = empExample.createCriteria();
        //Criteria对象可以拼接一系列sql操作,同一个Criteria对象拼接的sql之间只能是and逻辑
        c1.andEnameLike("%人%");
        c1.andDepartmentidEqualTo("JS");

        //在同一个Example对象下创建第二个Criteria对象
        EmpExample.Criteria c2 = empExample.createCriteria();
        c2.andAgeEqualTo(21);

        //同一个Example对象的不同Criteria对象之间可以进行or操作
        empExample.or(c2);//这里参数传递c1或c2均可

        List<Emp> emps = mapper.selectByExample(empExample);
        for(Emp emp : emps){
            System.out.println(emp);
        }
    }
}

特点:

  • 创建 Example 对象,该对象用于创建 Criteria 对象。
  • Criteria 对象可以拼接一系列 sql 操作,同一个 Criteria 对象拼接的 sql 之间只能是 and 逻辑。
  • 在同一个 Example 对象下创建第二个 Criteria 对象。
  • 同一个 Example 对象的不同Criteria对象之间可以进行 or 操作。

PageHelper 分页

配置插件

MyBatis 提供插件:PageHelper,实现分页操作。

步骤:

  • 导入 jar 包。
    在这里插入图片描述

  • 在 核心配置文件中配置插件 plugins。注意配置文件各个标签的顺序。

<plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor"/>
</plugins>

PageHelper、PageInfo

  • PageHelper.startPage(int pageNum, int PageSize):设置起始页码,每页显示的信息数目,需要放在查询语句之前才能生效
  • PageInfo<T>(List list, int navigatePages):使用 PageInfo 包装查询后的结果,封装了详细的查询数据,T 为当前页面显示的数据类型。
    list:需要分页的数据集合
    navigatePages:搜索栏中显示的页码个数(12345),当前页的页码始终在中间
//需要放在查询语句之前才能生效
PageHelper.startPage(3, 2);//设置页面信息
//查询全部员工
List<Emp> empList = mapper.getAllEmps();
for(Emp emp : empList){
    System.out.println(emp);//显示在第2页的Emp有哪些
}
//PageInfo<T>(List list, int navigatePages)类:获取当前页面信息,T为当前页面保存的数据类型
//list:查询到的所有信息,navigatePages:搜索栏中显示的页码个数,当前页的页码始终在中间。
PageInfo<Emp> pageInfo = new PageInfo<>(empList, 3);//显示当前页:第2页的分页信息
System.out.println(Arrays.toString(pageInfo.getNavigatepageNums()));

在这里插入图片描述
在这里插入图片描述

模拟分页

PageUtils.java

package com.mcc.MyBatis.page;

import com.github.pagehelper.PageInfo;

public class PageUtils {
    //分页
    public static<T> String getPage(PageInfo<T> pageInfo){
        StringBuilder stringBuilder = new StringBuilder();
        String path = "http://loclalhost:8080/ssm/";
        //首页
        if(pageInfo.isHasPreviousPage()){
            stringBuilder.append("<a href='"+path+"emps/1"+"'>"+"首页"+"</a>");
        }
        stringBuilder.append(" ");
        //上一页
        if(pageInfo.isHasPreviousPage()){
            stringBuilder.append("<a href='"+path+"emps/"+pageInfo.getPrePage()+"'>"+"上一页"+"</a>");
        }
        stringBuilder.append(" ");
        //页码
        int[] nums = pageInfo.getNavigatepageNums();
        for (int num : nums) {
            if(num==pageInfo.getPageNum()){//获取当前页码
                stringBuilder.append("<a href='"+path+"emps/"+num+"' style='color:red;'>"+num+"</a>");
                stringBuilder.append(" ");
            }else{
                stringBuilder.append("<a href='"+path+"emps/"+num+"'>"+num+"</a>");
                stringBuilder.append(" ");
            }
        }
        //下一页
        if(pageInfo.isHasNextPage()){
            stringBuilder.append("<a href='"+path+"emps/"+pageInfo.getNextPage()+"'>"+"下一页"+"</a>");
        }
        stringBuilder.append(" ");
        //尾页
        if(pageInfo.isHasNextPage()){
            stringBuilder.append("<a href='"+path+"emps/"+pageInfo.getPages()+"'>"+"尾页"+"</a>");
        }
        //StringBuilder转化为字符串返回
        String pageStr = stringBuilder.toString();
        return pageStr;
    }
}

测试:

package com.mcc.MyBatis.test;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mcc.MyBatis.bean.Emp;
import com.mcc.MyBatis.mapper.EmpMapper;
import com.mcc.MyBatis.page.PageUtils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class TestPages {
    @Test
    public void testPages() throws IOException {
        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.startPage(1, 3);
        //查询全部员工
        List<Emp> emps = mapper.getAllEmps();
        //将全部员工分页显示,栏有5个
        PageInfo<Emp> pageInfo = new PageInfo<>(emps, 5);
        String page = PageUtils.getPage(pageInfo);
        System.out.println(page);
    }
}

结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值