MyBatis·基础篇(八) MyBatis中的连接池技术
1. MyBatis连接池分类
在 MyBatis 的数据源 dataSource 分为以下几类:
- UNPOOLED 不使用连接池的数据源
- POOLED 使用连接池的数据源
- JNDI 使用 JNDI 实现的数据源
2. Mybatis 中数据源的配置
我们的数据源配置就是在 SqlMapConfig.xml 文件中,具体配置如下:
<!-- 配置数据源(连接池)信息 -->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
MyBatis 在初始化时,根据的 type 属性来创建相应类型的的数据源 DataSource,即:
- type=”POOLED”:MyBatis 会创建 PooledDataSource 实例
- type=”UNPOOLED” : MyBatis 会创建 UnpooledDataSource 实例
- type=”JNDI”:MyBatis 会从 JNDI 服务上查找 DataSource 实例,然后返回使用
3 UNPOOLED 和 POOLED对比
-
UNPOOLED– 这个数据源的实现只是每次被请求时打开和关闭连接。虽然有点慢,但对于在数据库连接可用性方面没有太高要求的简单应用程序来说,是一个很好的选择。
-
POOLED– 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这是一种使得并发 Web 应用快速响应请求的流行处理方式。
4 Mybatis 中DataSource的存取
MyBatis 是 通 过 工 厂 模 式 来 创 建 数 据 源 DataSource 对 象 的 , MyBatis 定 义 了 抽 象 的 工 厂 接口:org.apache.ibatis.datasource.DataSourceFactory,通过其 getDataSource()方法返回数据源
DataSource,下面是 DataSourceFactory.class 源码:
MyBatis 创建了 DataSource 实例后,会将其放到 Configuration 对象内的 Environment 对象中, 供
以后使用,通过 Debug 跟踪代码:
- 打断点,然后下一步:
- 分析 factory 里的 configuration 对象的 environment 属性,结果如下:
结论:
连接池时存于 configuration 对象中
PooledDataSource 持有一个 UnpooledDataSource 的引用
5. Mybatis 中连接的获取过程分析
MyBatis 中获取连接对象采用了延迟加载策略,当我们创建 SqlSession 对象并执行SQL语句时,MyBatis才回去调用 dataSource 对象来创建 java.sql.Connection 对象。
为了验证这个延迟加载的特性,我们分别在测试类和 PooledDataSource.class 源码中的 popConnnection方法中打上断点,进行代码调试看看是执行哪一行代码时调用了获取连接的方法。
测试类:
PooledDataSource.class:
Debug运行测试类,逐行执行,发现到了执行SQL语句那一行时,进入了 PooledDataSource.class 的 popConnection 代码块中
结论:
最后我们可以发现,真正连接打开的时间点,只是在我们执行SQL语句时,才会进行。其实这样做我们也可以进一步发现,数据库连接是我们最为宝贵的资源,只有在要用到的时候,才去获取并打开连接,当我们用完了就再立即将数据库连接归还到连接池中。
6. JNDI 数据源(了解)
6.1 JNDI 介绍
JNDI:Java Naming and Directory Interface
是SUN公司推出的一套规范,属于JavaEE技术之一。目的是模仿windows系统中的注册表
6.2 MyBatis 中的 JNDI 数据源
JNDI是使用在服务器中注册的数据源,常用于整合其他连接池技术,但不能脱离服务器。
6.3 MyBatis中配置 JNDI 数据源
创建Maven的war工程并导入坐标
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
</dependency>
</dependencies>
在webapp文件下创建META-INF目录
在META-INF目录中建立一个名为context.xml的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<!--
<Resource
name="jdbc/mybatis" 数据源的名称
type="javax.sql.DataSource" 数据源类型
auth="Container" 数据源提供者
maxActive="20" 最大活动数
maxWait="10000" 最大等待时间
maxIdle="5" 最大空闲数
username="root" 用户名
password="1234" 密码
driverClassName="com.mysql.jdbc.Driver" 驱动类
url="jdbc:mysql://localhost:3306/eesy_mybatis" 连接url字符串
/>
-->
<Resource
name="jdbc/pool"
type="javax.sql.DataSource"
auth="Container"
maxActive="20"
maxWait="10000"
maxIdle="5"
username="root"
password="1234"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/mybatis"
/>
</Context>
这里使用的是Tomcat 内置的连接池技术 DBCP
修改SqlMapConfig.xml中的配置
<dataSource type="JNDI">
<property name="data_source" value="java:comp/env/jdbc/pool"/>
</dataSource>
在jsp中编写测试类
<%@ page import="java.io.InputStream" %>
<%@ page import="org.apache.ibatis.io.Resources" %>
<%@ page import="org.apache.ibatis.session.SqlSessionFactoryBuilder" %>
<%@ page import="org.apache.ibatis.session.SqlSessionFactory" %>
<%@ page import="org.apache.ibatis.session.SqlSession" %>
<%@ page import="com.itheima.dao.IUserDao" %>
<%@ page import="com.itheima.domain.User" %>
<%@ page import="java.util.List" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html>
<body>
<h2>Hello World!</h2>
<%
//1.读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.根据配置文件构建SqlSessionFactory
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3.使用SqlSessionFactory创建SqlSession对象
SqlSession sqlSession = factory.openSession();
//4.使用SqlSession构建Dao的代理对象
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
//5.执行dao中的findAll方法
List<User> users = userDao.findAll();
for(User user : users){
System.out.println(user);
}
//6.释放资源
sqlSession.close();
in.close();
%>
</body>
</html>
单独使用MyBatis时,常用 MyBatis 自带连接池技术,JNDI数据源不做重点学习,了解即可