JDBC 源码深度解析
一、JDBC 架构全景
JDBC 核心包结构
java.sql
├── Driver
├── DriverManager
├── Connection
├── Statement
│ ├── PreparedStatement
│ └── CallableStatement
├── ResultSet
└── SQLException
二、核心接口源码解析
1. Driver 接口
public interface Driver {
// 1. 建立数据库连接
Connection connect(String url, Properties info) throws SQLException;
// 2. 判断驱动是否支持指定URL
boolean acceptsURL(String url) throws SQLException;
// 3. 获取驱动属性信息
DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException;
// 4. 获取驱动版本信息
int getMajorVersion();
int getMinorVersion();
// 5. 判断驱动是否符合JDBC规范
boolean jdbcCompliant();
}
2. DriverManager 核心源码
public class DriverManager {
// 注册的驱动列表
private static final CopyOnWriteArrayList<DriverInfo> registeredDrivers =
new CopyOnWriteArrayList<>();
// 注册驱动
public static synchronized void registerDriver(Driver driver)
throws SQLException {
if (driver != null) {
registeredDrivers.add(new DriverInfo(driver));
} else {
throw new NullPointerException();
}
}
// 获取数据库连接
public static Connection getConnection(String url,
String user, String password) throws SQLException {
Properties props = new Properties();
if (user != null) props.put("user", user);
if (password != null) props.put("password", password);
return getConnection(url, props);
}
private static Connection getConnection(String url, Properties info) throws SQLException {
// 遍历所有注册的驱动
for (DriverInfo driverInfo : registeredDrivers) {
if (isDriverAllowed(driverInfo.driver, callerClass)) {
try {
// 尝试建立连接
Connection con = driverInfo.driver.connect(url, info);
if (con != null) return con;
} catch (SQLException ex) {
// 记录失败日志
}
}
}
throw new SQLException("No suitable driver found for " + url);
}
}
3. Connection 接口关键方法
public interface Connection extends AutoCloseable {
// 创建Statement
Statement createStatement() throws SQLException;
// 创建预编译Statement
PreparedStatement prepareStatement(String sql) throws SQLException;
// 创建存储过程Statement
CallableStatement prepareCall(String sql) throws SQLException;
// 事务控制
void setAutoCommit(boolean autoCommit) throws SQLException;
void commit() throws SQLException;
void rollback() throws SQLException;
// 元数据获取
DatabaseMetaData getMetaData() throws SQLException;
// 连接状态
boolean isClosed() throws SQLException;
boolean isValid(int timeout) throws SQLException;
}
三、核心实现类源码解析(以 MySQL 驱动为例)
1. MySQL Driver 实现
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
static {
try {
// 驱动加载时自动注册
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
public Driver() throws SQLException {
// Required for Class.forName().newInstance()
}
@Override
public Connection connect(String url, Properties info) throws SQLException {
// 检查URL格式
if (!url.startsWith("jdbc:mysql://")) {
return null;
}
// 创建真实连接
return new ConnectionImpl(host, port, props, database, url);
}
}
2. MySQL Connection 实现
public class ConnectionImpl implements JdbcConnection {
// 底层Socket连接
private SocketFactory socketFactory;
private Socket rawSocket;
private InputStream inputStream;
private OutputStream outputStream;
// 事务状态
private boolean autoCommit = true;
private int isolationLevel = TRANSACTION_REPEATABLE_READ;
public ConnectionImpl(String host, int port, Properties props, String database)
throws SQLException {
// 1. 建立网络连接
rawSocket = socketFactory.connect(host, port, props);
inputStream = rawSocket.getInputStream();
outputStream = rawSocket.getOutputStream();
// 2. 发送认证信息
sendAuthPacket(user, password, database);
// 3. 设置连接参数
if (!autoCommit) {
execSQL(null, "set autocommit=0", -1, null);
}
execSQL(null, "set isolation level " + isolationLevel, -1, null);
}
@Override
public Statement createStatement() throws SQLException {
return new StatementImpl(this);
}
@Override
public void commit() throws SQLException {
// 发送COMMIT命令
execSQL(null, "COMMIT", -1, null);
}
}
3. Statement 实现
public class StatementImpl implements Statement {
protected ConnectionImpl connection;
protected ResultSetInternalMethods resultSet;
// 执行查询
public ResultSet executeQuery(String sql) throws SQLException {
// 1. 清除之前的结果
reset();
// 2. 发送SQL到数据库
Buffer sendPacket = new Buffer(sql);
connection.sendCommand(sendPacket);
// 3. 获取结果集
resultSet = connection.readAllResults(this, resultSetType);
return resultSet;
}
// 执行更新
public int executeUpdate(String sql) throws SQLException {
reset();
Buffer sendPacket = new Buffer(sql);
connection.sendCommand(sendPacket);
// 获取影响行数
return (int) connection.getLastRowCount();
}
// 批处理
public void addBatch(String sql) throws SQLException {
batchedArgs.add(sql);
}
public int[] executeBatch() throws SQLException {
int[] updateCounts = new int[batchedArgs.size()];
for (int i = 0; i < batchedArgs.size(); i++) {
updateCounts[i] = executeUpdate(batchedArgs.get(i));
}
return updateCounts;
}
}
4. PreparedStatement 实现
public class PreparedStatement extends StatementImpl implements PreparedStatement {
private String originalSql;
private BindValue[] bindValues;
public PreparedStatement(ConnectionImpl conn, String sql) {
super(conn);
this.originalSql = sql;
this.bindValues = parseBindValues(sql);
}
// 设置参数
public void setString(int parameterIndex, String x) throws SQLException {
bindValues[parameterIndex - 1].setString(x);
}
public void setInt(int parameterIndex, int x) throws SQLException {
bindValues[parameterIndex - 1].setInt(x);
}
// 执行预编译语句
public ResultSet executeQuery() throws SQLException {
String parsedSql = parseSqlWithBindValues();
return super.executeQuery(parsedSql);
}
private String parseSqlWithBindValues() {
StringBuilder sb = new StringBuilder();
int pos = 0;
for (BindValue bindValue : bindValues) {
sb.append(originalSql, pos, bindValue.position);
sb.append(bindValue.toString());
pos = bindValue.position + 1;
}
sb.append(originalSql.substring(pos));
return sb.toString();
}
}
5. ResultSet 实现
public class ResultSetImpl implements ResultSet {
private List<RowData> rows;
private int currentRow = -1;
private RowData currentRowData;
// 遍历结果
public boolean next() throws SQLException {
if (currentRow + 1 < rows.size()) {
currentRow++;
currentRowData = rows.get(currentRow);
return true;
}
return false;
}
// 获取列值
public String getString(int columnIndex) throws SQLException {
return currentRowData.getString(columnIndex - 1);
}
public int getInt(int columnIndex) throws SQLException {
return currentRowData.getInt(columnIndex - 1);
}
// 元数据
public ResultSetMetaData getMetaData() throws SQLException {
return new ResultSetMetaDataImpl(this);
}
}
四、JDBC 工作流程源码解析
1. 连接建立过程
2. 查询执行过程
五、高级特性实现
1. 连接池实现原理
public class ConnectionPool {
private final BlockingQueue<PooledConnection> idleConnections;
private final List<PooledConnection> activeConnections;
public Connection getConnection() throws SQLException {
PooledConnection conn = idleConnections.poll();
if (conn == null) {
if (activeConnections.size() < maxPoolSize) {
conn = createNewConnection();
} else {
// 等待可用连接
conn = idleConnections.poll(waitTime, TimeUnit.MILLISECONDS);
}
}
activeConnections.add(conn);
return conn.getProxyConnection();
}
private PooledConnection createNewConnection() throws SQLException {
Connection rawConn = DriverManager.getConnection(url, props);
return new PooledConnection(rawConn);
}
}
class PooledConnection {
private final Connection realConnection;
private final Connection proxyConnection;
public PooledConnection(Connection realConn) {
this.realConnection = realConn;
this.proxyConnection = createProxy();
}
private Connection createProxy() {
return (Connection) Proxy.newProxyInstance(
getClass().getClassLoader(),
new Class[]{Connection.class},
(proxy, method, args) -> {
if ("close".equals(method.getName())) {
// 重写close方法:归还连接
returnConnectionToPool();
return null;
}
return method.invoke(realConnection, args);
});
}
}
2. 事务管理实现
public class JdbcTransaction {
private Connection connection;
private boolean autoCommit;
public void begin() throws SQLException {
autoCommit = connection.getAutoCommit();
connection.setAutoCommit(false);
}
public void commit() throws SQLException {
connection.commit();
connection.setAutoCommit(autoCommit);
}
public void rollback() throws SQLException {
connection.rollback();
connection.setAutoCommit(autoCommit);
}
// 事务隔离级别控制
public void setIsolationLevel(int level) throws SQLException {
connection.setTransactionIsolation(level);
}
}
3. 元数据获取实现
public class DatabaseMetaDataImpl implements DatabaseMetaData {
public ResultSet getTables(String catalog, String schemaPattern,
String tableNamePattern, String[] types) throws SQLException {
String sql = "SELECT TABLE_CAT, TABLE_SCHEM, TABLE_NAME, TABLE_TYPE " +
"FROM INFORMATION_SCHEMA.TABLES " +
"WHERE TABLE_CAT LIKE ? AND TABLE_SCHEM LIKE ? " +
"AND TABLE_NAME LIKE ? AND TABLE_TYPE IN (?)";
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setString(1, catalog);
stmt.setString(2, schemaPattern);
stmt.setString(3, tableNamePattern);
stmt.setString(4, String.join(",", types));
return stmt.executeQuery();
}
}
六、性能优化关键源码
1. 批处理优化
public class BatchExecutor {
private List<String> batchSQL = new ArrayList<>();
private Connection connection;
public void addBatch(String sql) {
batchSQL.add(sql);
}
public int[] executeBatch() throws SQLException {
try (Statement stmt = connection.createStatement()) {
// 关闭自动提交
connection.setAutoCommit(false);
for (String sql : batchSQL) {
stmt.addBatch(sql);
}
int[] results = stmt.executeBatch();
connection.commit();
return results;
} catch (SQLException ex) {
connection.rollback();
throw ex;
} finally {
connection.setAutoCommit(true);
batchSQL.clear();
}
}
}
2. 结果集分页
public class PaginationResultSet implements ResultSet {
private ResultSet realResultSet;
private int offset;
private int limit;
private int currentRow = 0;
public PaginationResultSet(ResultSet rs, int offset, int limit) {
this.realResultSet = rs;
this.offset = offset;
this.limit = limit;
}
public boolean next() throws SQLException {
// 跳过offset之前的行
while (currentRow < offset && realResultSet.next()) {
currentRow++;
}
// 获取limit范围内的行
if (currentRow < offset + limit && realResultSet.next()) {
currentRow++;
return true;
}
return false;
}
}
七、JDBC 设计模式应用
- 桥接模式 - DriverManager 与 Driver 实现分离
- 工厂模式 - Connection 创建 Statement
- 代理模式 - 连接池返回代理连接
- 模板方法 - 通用查询执行流程
- 装饰器模式 - 结果集增强功能
八、源码分析建议
-
调试入口:
// 启用JDBC日志 DriverManager.setLogWriter(new PrintWriter(System.out)); // 查看驱动加载 Class.forName("com.mysql.cj.jdbc.Driver");
-
核心跟踪点:
DriverManager.getConnection()
ConnectionImpl
构造函数StatementImpl.executeQuery()
ResultSetImpl.next()
-
学习资源:
- OpenJDK: java.sql 包源码
- MySQL Connector/J 源码
- HikariCP 连接池源码
通过深入JDBC源码,可以掌握:
- 数据库连接建立机制
- SQL执行和结果解析流程
- 事务控制底层实现
- 连接池高效管理原理
- 跨数据库兼容性设计