今天的代码比较易懂 //下面是创建拿到连接之后,创建Statement的逻辑
public void checkState() throws SQLException { final boolean asyncCloseEnabled; if (holder != null) { //判断连接是否关闭 asyncCloseEnabled = holder.getDataSource().isAsyncCloseConnectionEnable(); } else { asyncCloseEnabled = false; } if (asyncCloseEnabled) { lock.lock(); try { checkStateInternal(); } finally { lock.unlock(); } } else { checkStateInternal(); } }
void initStatement(DruidPooledConnection conn, Statement stmt) throws SQLException { // transaction: 事务是否是自动提交 boolean transaction = !conn.getConnectionHolder().underlyingAutoCommit; // queryTimeout: 超时时间 int queryTimeout = transaction ? getTransactionQueryTimeout() : getQueryTimeout(); if (queryTimeout > 0) { stmt.setQueryTimeout(queryTimeout); } }
public Statement createStatement() throws SQLException { //1.上来要先检察一下连接是否可用 checkState(); Statement stmt = null; try { stmt = conn.createStatement(); } catch (SQLException ex) { handleException(ex, null); } holder.getDataSource().initStatement(this, stmt); DruidPooledStatement poolableStatement = new DruidPooledStatement(this, stmt); //List<Statement> 缓存到到这个list中 holder.addTrace(poolableStatement); return poolableStatement; }
protected void transactionRecord(String sql) throws SQLException { if (holder != null) { holder.setLastExecTimeMillis(System.currentTimeMillis()); } if (transactionInfo == null && (!conn.getAutoCommit())) { // DruidAbstractDataSource dataSource = holder.getDataSource(); //统计transactionCount的数量 dataSource.incrementStartTransactionCount(); transactionInfo = new TransactionInfo(dataSource.createTransactionId()); } if (transactionInfo != null) { //在connection上绑定transactionInfo的属性,在transactionInfo中包含sql语句 List<String> sqlList = transactionInfo.getSqlList(); if (sqlList.size() < MAX_RECORD_SQL_COUNT) { sqlList.add(sql); } } }
//查询 public final ResultSet executeQuery(String sql) throws SQLException { checkOpen(); // incrementExecuteQueryCount(); transactionRecord(sql); conn.beforeExecute(); try { ResultSet rs = stmt.executeQuery(sql); if (rs == null) { return rs; } DruidPooledResultSet poolableResultSet = new DruidPooledResultSet(this, rs); // addResultSetTrace(poolableResultSet); return poolableResultSet; } catch (Throwable t) { errorCheck(t); throw checkException(t, sql); } finally { conn.afterExecute(); } }
protected void addResultSetTrace(ResultSet resultSet) { if (resultSetTrace == null) { resultSetTrace = new ArrayList<ResultSet>(1); } else if (resultSetTrace.size() > 0) { int lastIndex = resultSetTrace.size() - 1; ResultSet lastResultSet = resultSetTrace.get(lastIndex); try { if (lastResultSet.isClosed()) { resultSetTrace.set(lastIndex, resultSet); return; } } catch (SQLException ex) { // skip } } //缓存resultSetTrace resultSetTrace.add(resultSet); }
//通过以上的方法拿到查询语句.查询完关闭连接
protected void recycle(DruidPooledConnection pooledConnection) throws SQLException { final DruidConnectionHolder holder = pooledConnection.holder; if (holder == null) { LOG.warn("connectionHolder is null"); return; } if (logDifferentThread // && (!isAsyncCloseConnectionEnable()) // && pooledConnection.ownerThread != Thread.currentThread()// ) { LOG.warn("get/close not same thread"); } final Connection physicalConnection = holder.conn; if (pooledConnection.traceEnable) { Object oldInfo = null; activeConnectionLock.lock(); try { if (pooledConnection.traceEnable) { oldInfo = activeConnections.remove(pooledConnection); pooledConnection.traceEnable = false; } } finally { activeConnectionLock.unlock(); } if (oldInfo == null) { if (LOG.isWarnEnabled()) { LOG.warn("remove abandonded failed. activeConnections.size " + activeConnections.size()); } } } final boolean isAutoCommit = holder.underlyingAutoCommit; final boolean isReadOnly = holder.underlyingReadOnly; final boolean testOnReturn = this.testOnReturn; try { // check need to rollback? if ((!isAutoCommit) && (!isReadOnly)) { pooledConnection.rollback(); } // reset holder, restore default settings, clear warnings boolean isSameThread = pooledConnection.ownerThread == Thread.currentThread(); if (!isSameThread) { final ReentrantLock lock = pooledConnection.lock; lock.lock(); try { holder.reset(); } finally { lock.unlock(); } } else { holder.reset(); } if (holder.discard) { return; } if (phyMaxUseCount > 0 && holder.useCount >= phyMaxUseCount) { discardConnection(holder); return; } if (physicalConnection.isClosed()) { lock.lock(); try { if (holder.active) { activeCount--; holder.active = false; } closeCount++; } finally { lock.unlock(); } return; } if (testOnReturn) { boolean validate = testConnectionInternal(holder, physicalConnection); if (!validate) { JdbcUtils.close(physicalConnection); destroyCountUpdater.incrementAndGet(this); lock.lock(); try { if (holder.active) { activeCount--; holder.active = false; } closeCount++; } finally { lock.unlock(); } return; } } if (holder.initSchema != null) { holder.conn.setSchema(holder.initSchema); holder.initSchema = null; } if (!enable) { discardConnection(holder); return; } boolean result; final long currentTimeMillis = System.currentTimeMillis(); if (phyTimeoutMillis > 0) { long phyConnectTimeMillis = currentTimeMillis - holder.connectTimeMillis; if (phyConnectTimeMillis > phyTimeoutMillis) { discardConnection(holder); return; } } lock.lock(); try { if (holder.active) { activeCount--; holder.active = false; } closeCount++; result = putLast(holder, currentTimeMillis); recycleCount++; } finally { lock.unlock(); } if (!result) { JdbcUtils.close(holder.conn); LOG.info("connection recyle failed."); } } catch (Throwable e) { holder.clearStatementCache(); if (!holder.discard) { discardConnection(holder); holder.discard = true; } LOG.error("recyle error", e); recycleErrorCountUpdater.incrementAndGet(this); } }