往期内容,如下
一、MyBatis简介
二、MyBatis环境搭建
三、MyBatis入门案例
四、MyBatis自定义
五、MyBatis CRUD操作
六、Mybatis中参数和返回值的深入了解
七、MyBatis 配置文件标签
我们在实际开发中都会使用连接池,因为它可以减少我们获取连接所消耗的时间,在这里就不在赘述了。
mybatis连接池配置的位置:主配置文件SqlMapConfig.xml
中的dataSource
标签,type
属性就是表示采用何种连接池方式
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 配置properties-->
<properties resource="jdbcConfig.properties"></properties>
<!--使用typeAliases配置别名,它只能配置domain中类的别名 -->
<typeAliases>
<package name="com.itheima.domain"></package>
</typeAliases>
<!--配置环境-->
<environments default="mysql">
<!-- 配置mysql的环境-->
<environment id="mysql">
<!-- 配置事务 -->
<transactionManager type="JDBC"></transactionManager>
<!--配置连接池-->
<dataSource type="POOLED"><!-- ============================================ -->
<property name="driver" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</dataSource>
</environment>
</environments>
<!-- 配置映射文件的位置 -->
<mappers>
<package name="com.itheima.dao"></package>
</mappers>
</configuration>
type属性的取值:
- POOLED:采用传统的
javax.sql.DataSource
规范中的连接池,mybatis中有针对规范的实现 - UNPOOLED:采用传统的获取连接的方式,虽然也实现
Javax.sql.DataSource
接口,但是并没有使用池的思想 - JNDI:采用服务器提供的
JNDI
技术实现,来获取DataSource
对象,不同的服务器所能拿到DataSource
是不一样(如果不是web
或者maven
的war工程,是不能使用的)
我们课程中使用的是tomcat服务器,采用连接池就是dbcp
连接池
IDEA 快捷键Ctrl+N,打开PooledDataSource.java
//找到getConnection方法
public Connection getConnection() throws SQLException {
return this.popConnection(this.dataSource.getUsername(), this.dataSource.getPassword()).getProxyConnection();
}
//=========================================================================================
//Ctrl+左键进入popConnection方法,截取部分代码
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.");
}
//=========================================================================================
//跟进去idleConnection方法
//可以发现idleConnection是一个集合
protected final List<PooledConnection> idleConnections = new ArrayList();
//=========================================================================================
回到popConnection方法
private PooledConnection popConnection(String username, String password) throws SQLException {
boolean countedWait = false;
PooledConnection conn = null;
long t = System.currentTimeMillis();
int localBadConnectionCount = 0;
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);//如果小于,new一个空闲的connection,从dataSource哪一个连接出来
if (log.isDebugEnabled()) {
log.debug("Created connection " + conn.getRealHashCode() + ".");
}
} else {//没有空闲连接,活动连接池又没有空闲的地方
PooledConnection oldestActiveConnection = (PooledConnection)this.state.activeConnections.get(0);//获取活动连接池中最老的一个连接出来
long longestCheckoutTime = oldestActiveConnection.getCheckoutTime();
if (longestCheckoutTime > (long)this.poolMaximumCheckoutTime) {
++this.state.claimedOverdueConnectionCount;
var10000 = this.state;
var10000.accumulatedCheckoutTimeOfOverdueConnections += longestCheckoutTime;
var10000 = this.state;
var10000.accumulatedCheckoutTime += longestCheckoutTime;
this.state.activeConnections.remove(oldestActiveConnection);
整个流程图如下