为什么mybatis中的SqlSession一定要关闭

目录
  • mybatis的SqlSession一定要关闭
    • 快的情况
    • 慢的情况
  • mybatis中SqlSession使用事项
    • 一.SqlSession的使用范围
    • 二.SqlSessionFactoryBuilder
    • 三.SqlSessionFactory
    • 四.SqlSession
    • 小结一下

mybatis的SqlSession一定要关闭

今天在使用mybatis查询数据时,出现了一个很奇怪的问题。同一条sql语句,查询时快时慢,并且有一定的规律性,大概每10次查询中有一次会特别特别的慢,快的只需要1ms,慢的要20000ms,sql代码及快慢时间截图如下:

select fknr from jq_fkqk where jjxh = ?

快的情况

慢的情况

通过日志打印mybatis查询信息时,我观察到特别慢的时候,并不是因为它查询很慢,而是因为它需要等待一段很长的时间才开始:

==> Preparing: select fknr from jq_fkqk where jjxh = ?

说明时间长就出现在这里,这个等待的时间。

  

为什么会要等待这么久呢?我自然而然的看了一下上一次查询的函数,发现在函数里面没有session.close(),把这一句加上,问题就解决了,速度就飞快了。

  

我本来想查看官方文档,查看原因,但是没找到,只能结合我自己的理解来分析一下。SqlSession是通过SqlSessionFactory来构造的,相当于维护一个连接池,当我们不停的进行查询的时候,由于没有关闭连接,导致与数据库的连接数量达到了一个上限(可能连接池有最大连接数,但是我们有找到文档)。

到达上限之后,再次请求查询时,Factory说没有连接了,让你先等一下,它先去判断哪些SqlSession已经没有人使用了(类似于垃圾回收机制),然后调用相应的进程去自动关闭没用的session连接,注意调用进程可是要排队的,也要耗时间。

等关闭了没有用的session之后,Factory通知你,有空闲的session了,开始准备你的查询吧,所有才会有等待很长一段时间才出现:

==> Preparing: select fknr from jq_fkqk where jjxh = ?

这纯属我自己的理解,但是重点还是表达出来了,就是Mybatis中的session一定要手动去关闭它,session.close(),不然会占着资源,导致性能下降!!!

mybatis中SqlSession使用事项

一.SqlSession的使用范围

SqlSession中存储的是编译好的sql语句,这些sql语句是mybatis配置文件读取mapper.xml文件生成的,将sql语句存储到SqlSessionFactory和SqlSession中。封装了对数据库的操作,如:查询、插入、更新、删除等。

通过SqlSessionFactory创建SqlSession,而SqlSessionFactory是通过SqlSessionFactoryBuilder加载配置文件进行创建。在开发中SqlSession在每次使用完都要进行关闭,使用时创建,也就是多例的,线程安全。SqlSessionFactory在整个类中只有一个对象,也就是单例的,单例的线程不安全。

二.SqlSessionFactoryBuilder

SqlSessionFactoryBuilder用于创建SqlSessionFacoty,SqlSessionFacoty一旦创建完成就不需要SqlSessionFactoryBuilder了,因为SqlSession是通过SqlSessionFactory生产,所以可以将SqlSessionFactoryBuilder当成一个工具类使用,最佳使用范围是方法范围即方法体内局部变量。

三.SqlSessionFactory

SqlSessionFactory是一个接口,接口中定义了openSession的不同重载方法,SqlSessionFactory的最佳使用范围是整个应用运行期间,一旦创建后可以重复使用,通常以单例模式管理SqlSessionFactory。

四.SqlSession

SqlSession是一个面向用户的接口, sqlSession中定义了数据库操作,默认使用DefaultSqlSession实现类。

执行过程如下:

1、加载数据源等配置信息

Environment environment = configuration.getEnvironment();

2、创建数据库链接

3、创建事务对象

4、创建Executor,SqlSession所有操作都是通过Executor完成,mybatis源码如下:

if (ExecutorType.BATCH == executorType) {
      executor = newBatchExecutor(this, transaction);
    } elseif (ExecutorType.REUSE == executorType) {
      executor = new ReuseExecutor(this, transaction);
    } else {
      executor = new SimpleExecutor(this, transaction);
    }
if (cacheEnabled) {
      executor = new CachingExecutor(executor, autoCommit);
    }

SqlSession的实现类即DefaultSqlSession,此对象中对操作数据库实质上用的是Executor

小结一下

每个线程都应该有它自己的SqlSession实例。SqlSession的实例不能共享使用,它也是线程不安全的。因此最佳的范围是请求或方法范围。绝对不能将SqlSession实例的引用放在一个类的静态字段或实例字段中。

打开一个 SqlSession;使用完毕就要关闭它。通常把这个关闭操作放到 finally 块中以确保每次都能执行关闭。如下:

    SqlSession session = sqlSessionFactory.openSession();
    try {
          // do work
    } finally {
          session.close();
    }

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Springboot 配置SqlSessionFactory方式

    目录 Springboot 配置SqlSessionFactory Springboot SqlSessionFactory错误 Springboot 配置SqlSessionFactory Spring官方提供了比较完善的数据库配置,但是某些情况下需要自己手动加载(如:配置多数据源) 以下是我搜集并整理出来的一个configuration,不足之处或错误请大家提出并指正 package cn.xt.config; import org.mybatis.spring.SqlSessionFact

  • mybatis spring配置SqlSessionTemplate的使用方式

    mybatis spring配置SqlSessionTemplate使用 1.application.xml配置 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance&quo

  • mybatis初始化SqlSessionFactory失败的几个原因分析

    目录 mybatis初始化SqlSessionFactory失败 总结原因有几点 SqlSessionFactory异常 mybatis初始化SqlSessionFactory失败 总结原因有几点 1.resources中的xml配置文件放错位置或者是放的太深加载不到 比如 RoleDao因为放的比较包中包中所以扫描不到 2.xml文件里面有错文 比如mapper namespace的相对路径有问题 导致初始化错误 SqlSessionFactory异常 org.springframework.

  • 关于springboot中对sqlSessionFactoryBean的自定义

    目录 springboot sqlSessionFactoryBean自定义 代码如下 以上配置也可以通过properties文件配置 springboot启动报找不到sqlSessionFactory springboot sqlSessionFactoryBean自定义 1.新建一个配置类,加上configuration注解 2.定制化SqlSessionFactoryBean,然后交给容器管理 代码如下 @Configuration public class MybatisConfig {

  • MyBatis源码解析——获取SqlSessionFactory方式

    目录 MyBatis源码解析_获取SqlSessionFactory 首先从Resources.getResourceAsReader(path) 进入到SqlSessionFactoryBuilder.build(Reader)方法中 进入到mapperElement(XNode)方法后 如果子节点名字不是package 经过一系列的解析,终于完成了 用MyBatis的配置文件获取SqlSessionFactory MyBatis源码解析_获取SqlSessionFactory 我们都知道,在

  • 浅谈Mybatis SqlSession执行流程

    目录 Mybatis执行SQL流程 SqlSession Executor Mybatis之Executor Mybatis之StatementHandler 进入ResultSetHandler Mybatis执行SQL流程 在看源码之前,我们需要了解一些基本知识,如果您没有阅读Mybatis SqlSessionFactory 初始化原理,可以先阅读Mybatis SqlSessionFactory 初始化原理这篇文章,这用更有助于我们理解接下来的文章 在看源码之前,我们需要了解一些基本知识

  • 基于SqlSessionFactory的openSession方法使用

    目录 SqlSessionFactory的openSession方法 创建Sqlsession的地方只有一个 我们可以看到实际创建SqlSession的地方 Executor的创建 Mapper MapperProxy的invoke openSession()到底做了什么 SqlSessionFactory的openSession方法 正如其名,Sqlsession对应着一次数据库会话. 由于数据库回话不是永久的,因此Sqlsession的生命周期也不应该是永久的,相反,在你每次访问数据库时都需

  • 为什么mybatis中的SqlSession一定要关闭

    目录 mybatis的SqlSession一定要关闭 快的情况 慢的情况 mybatis中SqlSession使用事项 一.SqlSession的使用范围 二.SqlSessionFactoryBuilder 三.SqlSessionFactory 四.SqlSession 小结一下 mybatis的SqlSession一定要关闭 今天在使用mybatis查询数据时,出现了一个很奇怪的问题.同一条sql语句,查询时快时慢,并且有一定的规律性,大概每10次查询中有一次会特别特别的慢,快的只需要1m

  • 关于MyBatis中SqlSessionFactory和SqlSession简解

    目录 [1]SqlSessionFactoryBuilder [2]SqlSessionFactory SqlSessionFactory 接口源码 SqlSessionFactory 有六个方法创建 SqlSession 实例 [3]非线程安全的SqlSession 永远不要在一个被管理域中引用SqlSession 语句执行方法 立即批量更新方法 事务控制方法 本地缓存 使用映射器 映射器注解 映射注解示例 mybatis官网中文文档:https://mybatis.org/mybatis-3

  • 获取Java的MyBatis框架项目中的SqlSession的方法

    从XML中构建SqlSessionFactory 从XML文件中构建SqlSessionFactory的实例非常简单.这里建议你使用类路径下的资源文件来配置. String resource = "org/mybatis/example/Configuration.xml"; Reader reader = Resources.getResourceAsReader(resource); sqlMapper = new SqlSessionFactoryBuilder().build(

  • MyBatis中SqlSession实现增删改查案例

    前言 开博客这是第一次写系列文章,从内心上讲是有点担心自己写不好,写不全,毕竟是作为java/mybatis学习的过程想把学习的路线和遇到的问题都总结下来,也让知识点在脑海里能形成一个体系. 开发环境 idea2016.mybatis3.SQLServer2012 pom.xml.mybatis.xml.log4j.properties 先贴上pom.xml是因为他直接和搭建开发环境和测试环境有关系,mybatis.xml则是连接数据库,log4j.properties在学习阶段配置上有助于我们

  • Mybatis中SqlSession下的四大对象之执行器(executor)

    首先我先解释一下标题 四大对象是指:executor, statementHandler,parameterHandler,resultHandler对象.(为了方便下面的文章说道四大对象就专指它们) 它们都是sqlSession的底层类实现,也是插件能够拦截的四大对象.所以这里已经触及了MyBATIS的底层,动态代理,反射随时可以看到,如果没有第一篇作为基础,你将十分难以理解它.了解他们的协作,是插件编写的基础之一,所以这是十分的重要. Executor在sqlSession中的应用 上篇我们

  • Mybatis中SqlSession接口中selectList方法详解

    目录 1.SqlSession简介 2.selectList方法 3.selectList方法简介 总结 1.SqlSession简介 SqlSession是mybatis持久层框架提供的接口,该接口中包含了大量的CRUD操作方法(既增删改查方法). 2.selectList方法 selectList方法是用于查询的方法,该方法具有多态性,如图所示(打开mybatis的SqlSession接口所得到) 3.selectList方法简介 该方法一共有三种不同的调用方式: List selectLi

  • 深入理解MyBatis中的一级缓存与二级缓存

    前言 先说缓存,合理使用缓存是优化中最常见的,将从数据库中查询出来的数据放入缓存中,下次使用时不必从数据库查询,而是直接从缓存中读取,避免频繁操作数据库,减轻数据库的压力,同时提高系统性能. 一级缓存 一级缓存是SqlSession级别的缓存.在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构用于存储缓存数据.不同的sqlSession之间的缓存数据区域是互相不影响的.也就是他只能作用在同一个sqlSession中,不同的sqlSession中的缓存是互相不能读取的. 一级缓

  • mybatis中的一级缓存深入剖析

    mybatis中提供有一级缓存 和 二级缓存,这里记录一下一级缓存 一级缓存(mybatis中默认开启) SqlSession级别的缓存,操作数据库时需要构造SQLSession对象, 在对象中有一个数据结构(HashMap)用于存储缓存数据,不同的SQLSession对象之间的缓存数据是不共享的,即独立的 根据第一点,简单一点讲就是一级缓存是属于对象的(个人记法) 从别处搞来一个图,便于我们理解: 下面用spring整合mybatis来测试一下mybatis的一级缓存: 1.下面是servic

  • MyBatis 中使用 Mapper 简化代码的方法

    前面文章所写的增删改查是存在问题的.每执行一次 SQL,都要开启一次会话,并且需要提交并关闭,主要问题就是冗余代码过多,模板化代码过多. 例如,我想开发一个 UserDao,可能是下面这样: 简化前的 UserDao public class UserDao { private SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getInstance(); public User getUserById(Integer id

  • MyBatis中XML 映射文件中常见的标签说明

    SQL 映射文件只有很少的几个顶级元素(按照应被定义的顺序列出): cache – 对给定命名空间的缓存配置. cache-ref – 对其他命名空间缓存配置的引用. resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象. parameterMap – 已被废弃!老式风格的参数映射.更好的办法是使用内联参数,此元素可能在将来被移除. sql – 可被其他语句引用的可重用语句块. insert – 映射插入语句 update – 映射更新语句 delete –

随机推荐