IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Mybatis入门学习记录(三):mybatis缓存及使用 -> 正文阅读

[Java知识库]Mybatis入门学习记录(三):mybatis缓存及使用

在说动态SQL前,我补充一下之前没有将的mybatis的缓存,嘿嘿~

一、mybatis缓存

在开讲之前,我先说一句:mybatis的缓存不是目前大家所能见到的软件会普遍使用的,因为mybatis缓存只是在每个人的电脑中存在,换一台电脑这个缓存就无啦!对减轻数据库压力基本没有什么帮助!只是大致的了解一下是怎么回事!因为软件开发市场上目前的主流是缓存服务器,像redis、noSQL等!这个我画一张图解释一下,就是这样:

mybatis的缓存:

分为一级缓存: 无法关闭,默认打开 缓存在SqlSession对象

二级缓存: 以Mapper的namespace分类, 同一个namespace的数据缓存到二级缓存,

Mybatis内部存储缓存使用一个HashMap,key为hashCode+sqlId+Sql语句。value为从查询出来映射生成的java对象

不同sqlSession,查询相同的statement, 走二级缓存, 数据可以共享

mybatis 的二级缓存默认是关闭。

开启mybatis的二级缓存:

1) 在Mybatis的全局配置文件中,允许使用二级缓存

 <settings>
        <!--允许使用二级缓存-->
        <setting name="cacheEnabled" value="true"/>
    </settings>

2) 在使用二级缓存的sql映射文件中使用 <cache/> 表示该mapper开启二级缓存

  <!--对该mapper开启二级缓存-->
    <cache/>

报错:

Caused by: java.io.NotSerializableException: com.fs.entity.User

原因: User实体类没有开启序列化

3) 对我们实体类实现序列化接口

@Data
public class User  implements Serializable {

对某个statement 禁用二级缓存:

select标签: 属性: useCache="true" 默认true, 使用缓存

useCache="false" 不使用缓存

  <select id="queryById" parameterType="int"  resultType="com.fs.entity.User" useCache="false">

自定义缓存框架:

1) 编写一个缓存类实现 org.apache.ibatis.cache.Cache接口

2) <cache type="指向的自定义缓存类包.类" />

之前的缓存框架: Ehcache

二、Mybatis的util工具类

核心类: SqlSessionFactory: 只能有一个

SqlSession: 每请求一次,创建一个SqlSession, 多例

每一次请求都有自己的SqlSession, 每一个线程都有自己的SqlSession

原因:SqlSession已关闭

引起原因: 多个线程共享了同一个SqlSession, SqlSession要线程隔离

ThreadLocal类

所以每个用户的电脑或者主机上都会有一个sqlSession用于存放自己访问这个APP时所使用的线程对象,我们可以根据这个SQLSession来实现多个请求多线程同时访问我们的数据库

?这是一个测试类用于测试多个线程同时访问发起请求,测试我们的多个SQLSession请求多线程访问我们的数据库会怎样(下面这个代码是已经完成的代码):

public class TestMybatisUtils {

    //开多个线程使用sqlSession

    public static void main(String[] args){
        new Thread(()->{
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            System.out.println("t1的SqlSession:"+sqlSession.hashCode());
            UserMapper userMapper =  sqlSession.getMapper(UserMapper.class);
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            User user = userMapper.queryById(1); //sqlSession.selectOne()
            System.out.println(user);

            MybatisUtils.closeSqlSession();
        }, "t1").start();

        new Thread(()->{
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            System.out.println("t2的SqlSession:"+sqlSession.hashCode());
            UserMapper userMapper =  sqlSession.getMapper(UserMapper.class);
            User user = userMapper.queryById(2);
            System.out.println(user);

            MybatisUtils.closeSqlSession();
        }, "t2").start();
    }
}

然后我们需要写一个mybatisUtils工具类用于实现每个用户发起请求时的在本地的sqlSession中存放相应的线程对象,并在合适的时候关闭它。

public class MybatisUtils {
    private static SqlSessionFactory sqlSessionFactory;
    //private static SqlSession sqlSession;  //单例, 整个共享同一个SqlSession
    private static ThreadLocal<SqlSession> tl = new ThreadLocal<>();
    //

    static{
        InputStream in = null;
        try {
            in = Resources.getResourceAsStream("mybatis-config.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 得到SqlSession方法
     */

    public static SqlSession getSqlSession(){
        //从当前执行的线程本地区获取SqlSession
        SqlSession sqlSession = tl.get();
        if( sqlSession== null){ //如果没有
            sqlSession = sqlSessionFactory.openSession(); //创建SqlSession
            tl.set(sqlSession);  //把创建SqlSession保存到当前线程的本地区
        }
        return sqlSession;
    }

    /**
     * 关闭SqlSession
     */
    public static void closeSqlSession(){
        SqlSession sqlSession = tl.get();
        if(sqlSession != null){
            sqlSession.commit();
            sqlSession.close();
            //把线程本地区的sqlSession移除
            tl.remove();
        }
    }


    /**
     * 得到指定Mapper类的对象
     * <T> 定义了泛型变量
     * T 使用泛型变量  返回值类型
     * Class<T>  T给泛型变量赋值
     */
    public static <T>  T getMapper(Class<T> clazz){
        return getSqlSession().getMapper(clazz);
    }
}

这样我们就能实现多线程访问数据库啦!我可能讲的还不是特别的清楚,所以希望大佬们看到了见谅,谢谢!感恩戴德!

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-11-29 16:10:49  更:2021-11-29 16:13:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:45:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码