MyBatis中的连接池
MyBatis连接池提供了三种方式的配置:
配置的位置:
主配置文件SqlMapConfig.xml中的dataSource标签,type属性就是采用何种连接池方式
type属性的取值:
POOLED
采用传统的javax.sql.DataSource
规范中的连接池,MyBatis中有针对规范的实现UNPOOLED
采用传统的获取连接的方式,虽然也实现Javax.sql.DataSource
接口,但是并没有使用池的思想。JNDI
采用服务器提供的JNDI技术实现,来获取DataSource
对象,不同的服务器所能拿到的DataSource
是不一样的。
MyBatis 内部分别定义了实现了 java.sql.DataSource 接口的UnpooledDataSource
,PooledDataSource
类来表示 UNPOOLED
、POOLED
类型的数据源。
MyBatis中DataSource的存取
MyBatis 是 通 过 工 厂 模 式 来 创 建 数 据 源 DataSource 对 象 的 , MyBatis 定 义 了 抽 象 的 工 厂 接口:org.apache.ibatis.datasource.DataSourceFactory
,通过其 getDataSource()
方法返回数据源DataSource
。
DataSourceFactory的源码:
package org.apache.ibatis.datasource;
import java.util.Properties;
import javax.sql.DataSource;
/**
* @author Clinton Begin
*/
public interface DataSourceFactory {
void setProperties(Properties props);
DataSource getDataSource();
}
MyBatis 创建了 DataSource 实例后,会将其放到 Configuration 对象内的 Environment 对象中, 供以后使用。
1.先进入XMLConfigBuidler类中,可以找到如下代码:
public class XMLConfigBuilder extends BaseBuilder {
private boolean parsed;
private final XPathParser parser;
private String environment;
private final ReflectorFactory localReflectorFactory;
............
public Configuration parse() {
if (this.parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
} else {
this.parsed = true;
this.parseConfiguration(this.parser.evalNode("/configuration"));
return this.configuration;
}
}
2.分析configuration对象的environment属性,结果如下:
MyBatis中连接获取过程分析
当我们需要创建 SqlSession
对象并需要执行 SQL 语句时,这时候 MyBatis 才会去调用 dataSource
对象来创建java.sql.Connection对象。也就是说,java.sql.Connection
对象的创建一直延迟到执行SQL语句的时候。
@Test
public void testSql() throws Exception {
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = factory.openSession();
List<User> list = sqlSession.selectList("findUserById",41);
System.out.println(list.size());
}
只有当第 4 句 sqlSession.selectList(“findUserById”),才会触发 MyBatis 在底层执行下面这个方法来创建 java.sql.Connection 对象。
如何证明它的加载过程呢?
1.POOLEAD通过源码分析
while(conn == null) {
synchronized(this.state) {
PoolState var10000;
if (!this.state.idleConnections.isEmpty()) {
conn = (PooledConnection)this.state.idleConnections.remove(0);
if (log.isDebugEnabled()) {
log.debug("Checked out connection " + conn.getRealHashCode() + " from pool.");
}
} else if (this.state.activeConnections.size() < this.poolMaximumActiveConnections) {
conn = new PooledConnection(this.dataSource.getConnection(), this);
if (log.isDebugEnabled()) {
log.debug("Created connection " + conn.getRealHashCode() + ".");
}
} else {
PooledConnection oldestActiveConnection = (PooledConnection)this.state.activeConnections.get(0);
long longestCheckoutTime = oldestActiveConnection.getCheckoutTime();
2.UNPOOLEAD分析
private Connection doGetConnection(Properties properties) throws SQLException {
this.initializeDriver();
Connection connection = DriverManager.getConnection(this.url, properties);
this.configureConnection(connection);
return connection;
}
private synchronized void initializeDriver() throws SQLException {
if (!registeredDrivers.containsKey(this.driver)) {
try {
Class driverType;
if (this.driverClassLoader != null) {
driverType = Class.forName(this.driver, true, this.driverClassLoader);
} else {
driverType = Resources.classForName(this.driver);
}
Driver driverInstance = (Driver)driverType.newInstance();
DriverManager.registerDriver(new UnpooledDataSource.DriverProxy(driverInstance));
registeredDrivers.put(this.driver, driverInstance);
} catch (Exception var3) {
throw new SQLException("Error setting driver on UnpooledDataSource. Cause: " + var3);
}
}
}
UNPOOLEAN是直接获取一个连接