首页 > 数据库 >Mybatis中的数据库连接池

Mybatis中的数据库连接池

时间:2022-09-02 16:25:22浏览次数:72  
标签:创建 数据库 MyBatis Connection DataSource Mybatis 连接池

mybatis中的数据库连接池

目录

一、前言

数据库连接和事务以及线程之间的关系这个章节中聊到了为什么需要数据库连接池,下面将从代码实战中来进行描述,然后来看看mybatis框架中利用的数据库连接池

二、为什么要使用数据库连接池

1、创建一个java.sql.Connection实例对象的代价

首先让我们来看一下创建一个java.sql.Connection对象的资源消耗。我们通过连接Oracle数据库,创建创建Connection对象,来看创建一个Connection对象、执行SQL语句各消耗多长时间。代码如下:

public class JDBCTest {
    public static void main(String[] args) throws SQLException {
        long start = new Date().getTime();
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/ie_draw", "root", "root");
        long end = new Date().getTime();
        System.out.println("创建数据库连接消耗的时间是:"+(end-start));
        String sql = "select count(*) from template";
        start = new Date().getTime();
        PreparedStatement preparedStatement = connection.prepareStatement("select count(*) from template");
        ResultSet resultSet = preparedStatement.executeQuery();
        end = new Date().getTime();
        System.out.println("耗时:"+(end-start));
    }
}

上述程序在我笔记本上的执行结果为:

创建数据库连接消耗的时间是:900
耗时:32

这让我多少是有点无语的。创建一个数据库连接的时间过长,而执行一个SQL的时间太短。

创建一个Connection对象用了900毫秒!这个时间对计算机来说可以说是一个非常奢侈的!

这仅仅是一个Connection对象就有这么大的代价,设想一下另外一种情况:如果我们在Web应用程序中,为用户的每一个请求就操作一次数据库,当有10000个在线用户并发操作的话,对计算机而言,仅仅创建Connection对象不包括做业务的时间就要损耗10000×900ms= 900 0000 ms = 9000 s = 150 min,竟然要150分钟!!!如果对高用户群体使用这样的系统,简直就是开玩笑!

2、问题分析

创建一个java.sql.Connection对象的代价是如此巨大,是因为创建一个Connection对象的过程,在底层就相当于和数据库建立的通信连接,在建立通信连接的过程,消耗了这么多的时间,而往往我们建立连接后(即创建Connection对象后),就执行一个简单的SQL语句,然后就要抛弃掉,这是一个非常大的资源浪费!

3、解决方案

对于需要频繁地跟数据库交互的应用程序,可以在创建了Connection对象,并操作完数据库后,可以不释放掉资源,而是将它放到内存中,当下次需要操作数据库时,可以直接从内存中取出Connection对象,不需要再创建了,这样就极大地节省了创建Connection对象的资源消耗。由于内存也是有限和宝贵的,这又对我们对内存中的Connection对象怎么有效地维护提出了很高的要求。我们将在内存中存放Connection对象的容器称之为 连接池(Connection Pool)。

三、Mybatis数据库连接池

下面让我们来看一下MyBatis的线程池是怎样实现的。

mybatis中datasource分类

MyBatis把数据源DataSource分为三种:

  • UNPOOLED 不使用连接池的数据源
  • POOLED 使用连接池的数据源
  • JNDI 使用JNDI实现的数据源

即:

相应地,MyBatis内部分别定义了实现了java.sql.DataSource接口的UnpooledDataSource,PooledDataSource类来表示UNPOOLED、POOLED类型的数据源。 如下图所示:

对于JNDI类型的数据源DataSource,则是通过JNDI上下文中取值。

mybatis中的数据库连接池创建

MyBatis数据源DataSource对象的创建发生在MyBatis初始化的过程中。

下面让我们一步步地了解MyBatis是如何创建数据源DataSource的。

在mybatis的XML配置文件中,使用元素来配置数据源:

MyBatis在初始化时,解析此文件,根据的type属性来创建相应类型的的数据源DataSource,即:

type=”POOLED” :MyBatis会创建PooledDataSource实例
type=”UNPOOLED” :MyBatis会创建UnpooledDataSource实例
type=”JNDI” :MyBatis会从JNDI服务上查找DataSource实例,然后返回使用

DataSourceFactory

顺便说一下,MyBatis是通过工厂模式来创建数据源DataSource对象的,MyBatis定义了抽象的工厂接口:org.apache.ibatis.datasource.DataSourceFactory,通过其getDataSource()方法返回数据源DataSource:

定义如下:

public interface DataSourceFactory {
 
  void setProperties(Properties props);
  //生产DataSource
  DataSource getDataSource();
}

上述三种不同类型的type,则有对应的以下dataSource工厂:

POOLED PooledDataSourceFactory
UNPOOLED UnpooledDataSourceFactory
JNDI JndiDataSourceFactory

其类图如下所示:

MyBatis创建了DataSource实例后,会将其放到Configuration对象内的Environment对象中, 供以后使用

DataSource什么时候创建Connection对象

当我们需要创建SqlSession对象并需要执行SQL语句时,这时候MyBatis才会去调用dataSource对象来创建java.sql.Connection对象。也就是说,java.sql.Connection对象的创建一直延迟到执行SQL语句的时候。

这里同样的,按照我们的之前的思想,一个线程和一个数据库连接对应的生命周期中。数据库连接的使用只是占据了一个线程的使用过程中一小部分。

如果存在着大量请求,我们的理想效果是,线程可以复用,数据库连接可以复用,那么系统处理效率高。

可以说,如果单位时间内,某个数据库连接被复用的频率越高,可以认为系统响应效率越快。

比如,我们有如下方法执行一个简单的SQL语句:

String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.selectList("SELECT * FROM STUDENTS");

前4句都不会导致java.sql.Connection对象的创建,只有当第5句sqlSession.selectList("SELECT * FROM STUDENTS"),才会触发MyBatis在底层执行下面这个方法来创建java.sql.Connection对象:

protected void openConnection() throws SQLException {
    if (log.isDebugEnabled()) {
      log.debug("Opening JDBC Connection");
    }
    connection = dataSource.getConnection();
    if (level != null) {
      connection.setTransactionIsolation(level.getLevel());
    }
    setDesiredAutoCommit(autoCommmit);
  }

而对于DataSource的UNPOOLED的类型的实现-UnpooledDataSource是怎样实现getConnection()方法的呢?

具体的参考:https://louluan.blog.csdn.net/article/details/37671851

因为我想的是在spring整合mybatis之后,肯定不会使用这种数据库连接池。

所以我在这里不再来进行研究。

标签:创建,数据库,MyBatis,Connection,DataSource,Mybatis,连接池
From: https://www.cnblogs.com/likeguang/p/16650361.html

相关文章

  • 优炫数据库安装步骤及.net core 集成
    优炫数据库的安装安装指定版本数据库文件。当前数据库文件:uxdb-std-win-x86_64-v2.1.1.4.exe根据优炫数据库指定安装文档说明安装数据库注意在倒数第二步骤,即安装步骤的第......
  • 地理空间数据库设计学习笔记(不分章)
    平时成绩40%,期末60%.平时成绩=考勤10%+作业20%+课堂表现作业=作业+实验报告C/S架构是什么?C/S架构,即Client/Server(客户端/服务器)架构,是一个典型的两层架构。通过将任务......
  • MyBatis-逆向工程
    1.逆向工程正向工程:先创建Java实体类,由框架负责根据实体类生成数据库表。Hibernate是支持正向工程的。逆向工程:先创建数据库表,由框架负责根据数据库表,反向生成如下资源......
  • MyBatis-缓存
    1.MyBatis缓存MyBatis中的缓存针对查询功能,可以将查询的数据进行缓存,再次查询相同数据时,不会从数据库中查询,直接从缓存中获取。分为一级缓存和二级缓存。2. MyBati......
  • Mybatis-plus Page<>分页失效,records返回全部
     问题:分页失效    page 是传了的,但是还是返回了全部数据。 这里需要加一个config文件 importcom.baomidou.mybatisplus.annotation.DbType;import......
  • mysql查询数据库和数据表占用内存大小
    --查看所有数据库容量大小selecttable_schemaas'数据库',sum(table_rows)as'记录数',sum(truncate(data_length/1024/1024/1024,2))as'数据容量(GB)',sum(truncate......
  • Mongodb数据库无故消失?
    一开始还以为是mongodb版本不支持持久化,直到我打开数据库连接,真的给我整笑了,我居然被黑了 内容是:Allyourdataisabackedup.Youmustpay0.01BTCtobc1q2......
  • ADO.net 使用存储过程 返回数据库中的数据集
    publicList<dFiledTree>d_BZWH_dis_BZFiled_ByType_ByTreeAs2(stringObjectType,stringUserName,intTypeAID){List<dFiledTree>list=n......
  • 3_将数据库连接方式写到配置文件中(转载)
    连接sqlserver的连接字符串asp.net项目配置文件:Web.config;winfrom项目配置文件:App.config<configuration><!--数据库连接-本地--><!--<connectionStrings><......
  • mybatis的实体类属性不存入数据库的排除方法
    网上有很多排除方法,但是因为框架问题都不适用,姑且展示一下1.@Transient该注解只适用于hibernate框架,在实体类(pojo)属性上使用、表示数据库表中没有这个字段就忽略;2.@Table......