为什么mybatis中的SqlSession一定要关闭
作者:玩人 发布时间:2022-02-24 07:57:11
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();
}
来源:https://blog.csdn.net/jeryjeryjery/article/details/79116735


猜你喜欢
- mybatis官网中文文档:https://mybatis.org/mybatis-3/zh/sqlmap-xml.htmlmybatis-
- 目标多级表头、分页、动态数据实现依赖<!-- poi工具类--> &nbs
- 本文实例讲述了Golang+Android基于HttpURLConnection实现的文件上传功能。分享给大家供大家参考,具体如下:这里要演
- 本文实例为大家分享了Android学习笔记之蓝牙功能的具体代码,供大家参考,具体内容如下蓝牙:短距离无线通讯技术标准。蓝牙协议分为4层,即核
- 本文实例讲述了C#实现对字符串进行大小写切换的方法。分享给大家供大家参考。具体实现方法如下:C#代码如下:public class Prog
- 本篇和大家分享的是通过maven对springboot中打war包和jar包;war通常来说生成后直接放到tomcat的webapps下面就
- 1.前言在Mybatis中需要创建的配置文件有sqlMapconfig.xml,映射文件xxxMapper.xml,而这些文件在idea中并
- 一、安装ElasticsearchElasticsearch下载地址:http://www.elasticsearch.org/downlo
- JNA(Java Native Access):建立在JNI之上的Java开源框架,SUN主导开发,用来调用C、C++代码,尤其是底层库文件
- 背景产品想对多次快速点击做一下优化,想要的效果就是双击不会打开多次但是从开发角度来说,我可以用kotlin的拓展方法来调整这个,但是之前的历
- 一.枚举和静态常量区别讲到枚举我们首先思考,它和public static final String 修饰的常量有什么不同。我举枚举的两个优
- 使用FastJson解决long类型在js中失去精度问题1.pom中需要将默认的jackson排除掉<dependency>&n
- C#实现多态主要有3种方法,虚方法,抽象类,接口1 虚方法在父类的方法前面加关键字virtual, 子类重写该方法时在方法名前面加上over
- 翻看印象笔记发现自己整理过arraycopy()这样一个方法,码字放到这里:System.arraycopy()是一个静态方法,用来实现重置
- 1、接口:一种把类抽象的更彻底,接口里只能包含抽象方法的“特殊类”。接口不关心类的内部状态数据,定义的是一批类所遵守的规范。(它只规定这批类
- 首先引入jar包:<dependency> <groupId>com.alibaba</grou
- 一、ObjectContext对象上下文Entity SQL 语言 - ADO.NET | Microsoft 官当文档ObjectCont
- 邮件绑定功能【需求】1、 用户注册时,输入邮箱2、 通过Javamail技术,向用户邮箱发送一封祝贺邮件1、javamail发送邮件1.1、
- 一、MessageBox弹出框MessageBox.Show(<字符串> Text, <字符串> Title, &l
- 如下所示://判断整数(int)private boolean isInteger(String str) {if (null == str