1.连接池:相当于线程池,线程也就是连接用完了要拿回去的。
接下来我们说下mybatis的连接池:
JNDI:不同的服务器拿到的dataSource是不一样的。
第一种:如果是POOLED则:从池中获取
对比下线程池:
第一个图拿了还回去了,第二个没有还回去。
源码:流程就是注册驱动,获取连接,返回连接。
我们看下
实现DataSource接口:
找到getConnection方法:
进去:
上面是
-----------------------------------------01-02-03-04----------------------------------------------------------
看下:
连接池拿链接是线程安全的,不能两个线程拿到同一个连接。
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) {
PoolState var8 = this.state;
synchronized(this.state) {
// 空闲的连接还有的话
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();
if (longestCheckoutTime > (long)this.poolMaximumCheckoutTime) {
++this.state.claimedOverdueConnectionCount;
this.state.accumulatedCheckoutTimeOfOverdueConnections += longestCheckoutTime;
this.state.accumulatedCheckoutTime += longestCheckoutTime;
this.state.activeConnections.remove(oldestActiveConnection);
if (!oldestActiveConnection.getRealConnection().getAutoCommit()) {
try {
oldestActiveConnection.getRealConnection().rollback();
} catch (SQLException var16) {
log.debug("Bad connection. Could not roll back");
}
}
conn = new PooledConnection(oldestActiveConnection.getRealConnection(), this);
conn.setCreatedTimestamp(oldestActiveConnection.getCreatedTimestamp());
conn.setLastUsedTimestamp(oldestActiveConnection.getLastUsedTimestamp());
oldestActiveConnection.invalidate();
if (log.isDebugEnabled()) {
log.debug("Claimed overdue connection " + conn.getRealHashCode() + ".");
}
} else {
try {
if (!countedWait) {
++this.state.hadToWaitCount;
countedWait = true;
}
if (log.isDebugEnabled()) {
log.debug("Waiting as long as " + this.poolTimeToWait + " milliseconds for connection.");
}
long wt = System.currentTimeMillis();
this.state.wait((long)this.poolTimeToWait);
this.state.accumulatedWaitTime += System.currentTimeMillis() - wt;
} catch (InterruptedException var17) {
break;
}
}
}
if (conn != null) {
if (conn.isValid()) {
if (!conn.getRealConnection().getAutoCommit()) {
conn.getRealConnection().rollback();
}
conn.setConnectionTypeCode(this.assembleConnectionTypeCode(this.dataSource.getUrl(), username, password));
conn.setCheckoutTimestamp(System.currentTimeMillis());
conn.setLastUsedTimestamp(System.currentTimeMillis());
this.state.activeConnections.add(conn);
++this.state.requestCount;
this.state.accumulatedRequestTime += System.currentTimeMillis() - t;
} else {
if (log.isDebugEnabled()) {
log.debug("A bad connection (" + conn.getRealHashCode() + ") was returned from the pool, getting another connection.");
}
++this.state.badConnectionCount;
++localBadConnectionCount;
conn = null;
if (localBadConnectionCount > this.poolMaximumIdleConnections + this.poolMaximumLocalBadConnectionTolerance) {
if (log.isDebugEnabled()) {
log.debug("PooledDataSource: Could not get a good connection to the database.");
}
throw new SQLException("PooledDataSource: Could not get a good connection to the database.");
}
}
}
}
}
if (conn == null) {
if (log.isDebugEnabled()) {
log.debug("PooledDataSource: Unknown severe error condition. The connection pool returned a null connection.");
}
throw new SQLException("PooledDataSource: Unknown severe error condition. The connection pool returned a null connection.");
} else {
return conn;
}
}
源码分析:
注意这个是一个集合。
去连接池拿连接的方式:
1.如果有空闲的连接,直接拿空闲的连接
2.活动连接池连接最大的数量小于设定的最大值,则新建一个连接
3.在连接池拿到最老的连接
两个池子,一个空闲池,一个活动池:
对应的是:PooledDataSource
第二种:如果是UNPOOLED则:每次创建新的
对应的是:UnpooledDataSource
代码:
private Connection doGetConnection(Properties properties) throws SQLException {
this.initializeDriver();
Connection connection = DriverManager.getConnection(this.url, properties);
this.configureConnection(connection);
return connection;
}
我们在实际开发中:
<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>
-------------------------------------------05-----------------------------------------------
事务:
sqlSession的commit和rollback方法。
这样的话我们每次都是自己进行的commit。
这个方法可以使我们的提交变为自动的提交的。
如何修改:
第一步:开启自动提交
自动提交不是常用的因为这样就控制不好事务了。
第二步:测试。