深入解析JDBC源码
作者:赖皮小王子 | 来源:互联网 | 2024-12-25 19:59
本文详细探讨了JDBC(Java数据库连接)的内部机制,重点分析其作为服务提供者接口(SPI)框架的应用。通过类图和代码示例,展示了JDBC如何注册驱动程序、建立数据库连接以及执行SQL查询的过程。
### JDBC概述 JDBC是Java应用程序与关系型数据库进行交互的标准API。它遵循服务提供者接口(SPI)模式,使得不同数据库厂商可以为JDBC接口提供具体实现。 #### 类图 JDBC的核心类和接口包括`DriverManager`、`Driver`、`Connection`、`Statement`和`ResultSet`等。这些类和接口共同构成了JDBC的桥梁设计模式,将用户端的操作与数据库端的具体实现分离。 #### 示例代码 以下是一个简单的JDBC代码示例,展示了如何注册驱动程序、建立连接、执行查询并处理结果: ```java public void baseTest() throws SQLException, ClassNotFoundException { // 设置日志输出 DriverManager.setLogWriter(new PrintWriter(System.out)); // 建立连接 String url = "jdbc:mysql://127.0.0.1:3306/jdbc"; String user = "root"; String password = "123"; Connection cOnn= DriverManager.getConnection(url, user, password); // 创建语句 Statement st = conn.createStatement(); // 执行查询 ResultSet rs = st.executeQuery("select * from user"); // 处理结果 while (rs.next()) { System.out.println(rs.getObject(1) + "\t" + rs.getObject(2) + "\t" + rs.getObject(3) + "\t" + rs.getObject(4)); } // 释放资源 rs.close(); st.close(); conn.close(); } ``` ### 驱动注册与连接获取 在初始化时,`loadInitialDrivers()`方法会读取系统属性`jdbc.drivers`,并加载相应的驱动程序。此外,它还会使用`ServiceLoader`查找并加载META-INF/services目录下描述的实现了`Driver`接口的驱动类。 ```java private static void loadInitialDrivers() { String drivers = AccessController.doPrivileged(new PrivilegedAction() { public String run() { return System.getProperty("jdbc.drivers"); } }); if (drivers == null || drivers.isEmpty()) { return; } String[] driversList = drivers.split(":"); for (String driver : driversList) { try { Class.forName(driver, true, ClassLoader.getSystemClassLoader()); } catch (Exception ex) { // 处理异常 } } } ``` 如果JAR文件中没有在META-INF/services中描述驱动程序,则需要手动注册驱动。通常情况下,调用`Class.forName()`会自动触发驱动程序的注册。 ```java public static synchronized void registerDriver(Driver driver) throws SQLException { if (driver != null) { registeredDrivers.addIfAbsent(new DriverInfo(driver)); } else { throw new NullPointerException(); } println("registerDriver: " + driver); } ``` ### 获取数据库连接 `DriverManager.getConnection()`方法会遍历已注册的驱动程序,尝试根据提供的URL建立连接。如果找到合适的驱动程序并成功连接,则返回`Connection`对象;否则抛出异常。 ```java private static Connection getConnection(String url, Properties info, Class> caller) throws SQLException { ClassLoader callerCL = caller != null ? caller.getClassLoader() : null; if (url == null) { throw new SQLException("The url cannot be null", "08001"); } for (DriverInfo aDriver : registeredDrivers) { if (isDriverAllowed(aDriver.driver, callerCL)) { try { Connection con = aDriver.driver.connect(url, info); if (con != null) { return con; } } catch (SQLException ex) { // 记录异常 } } } throw new SQLException("No suitable driver found for " + url, "08001"); } ``` ### MySQL连接示例 MySQL驱动程序通过解析URL来确定连接类型,并返回具体的`Connection`对象。 ```java public Connection connect(String url, Properties info) throws SQLException { if (url != null) { if (url.startsWith("jdbc:mysql:loadbalance://")) { return connectLoadBalanced(url, info); } if (url.startsWith("jdbc:mysql:replication://")) { return connectReplicationConnection(url, info); } } Properties props = parseURL(url, info); if (props == null) { return null; } try { com.mysql.jdbc.Connection cOnn= ConnectionImpl.getInstance(host(props), port(props), props, database(props), url); return conn; } catch (SQLException e) { throw e; } catch (Exception e) { throw SQLError.createSQLException(e.getMessage(), "08001", null); } } ``` ### 设计模式 JDBC广泛使用了桥梁设计模式和工厂方法设计模式。桥梁设计模式通过`DriverManager`和`Driver`桥接用户端和数据库端,而工厂方法设计模式则由具体的`Driver`生成`Connection`对象。
推荐阅读
实体映射最强工具类:MapStruct真香 ...
[详细]
蜡笔小新 2024-12-25 16:22:17
1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ...
[详细]
蜡笔小新 2024-12-27 19:32:17
Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ...
[详细]
蜡笔小新 2024-12-28 08:54:34
本文详细介绍了Spring Cloud中的Ribbon组件如何实现服务调用的负载均衡。通过分析其工作原理、源码结构及配置方式,帮助读者理解Ribbon在分布式系统中的重要作用。 ...
[详细]
蜡笔小新 2024-12-27 16:01:25
本文介绍了如何通过 Maven 依赖引入 SQLiteJDBC 和 HikariCP 包,从而在 Java 应用中高效地连接和操作 SQLite 数据库。文章提供了详细的代码示例,并解释了每个步骤的实现细节。 ...
[详细]
蜡笔小新 2024-12-26 17:34:42
本文深入探讨了Kubernetes集群的架构和核心对象,详细介绍了Pod、Service、Volume等基本组件,以及更高层次的抽象如Deployment、StatefulSet等,帮助读者全面理解Kubernetes的工作原理。 ...
[详细]
蜡笔小新 2024-12-26 14:15:32
在处理Java项目中的JAR包冲突时,我们遇到了JaxWsDynamicClientFactory被弃用的问题,并成功将其迁移到org.codehaus.xfire.client。本文详细介绍了这一过程及解决方案。 ...
[详细]
蜡笔小新 2024-12-25 18:48:34
本文探讨了 Spring Boot 应用程序在不同配置下支持的最大并发连接数,重点分析了内置服务器(如 Tomcat、Jetty 和 Undertow)的默认设置及其对性能的影响。 ...
[详细]
蜡笔小新 2024-12-25 16:45:57
本文详细介绍了 Apache Shiro,一个强大且灵活的开源安全框架。Shiro 专注于简化身份验证、授权、会话管理和加密等复杂的安全操作,使开发者能够更轻松地保护应用程序。其核心目标是提供易于使用和理解的API,同时确保高度的安全性和灵活性。 ...
[详细]
蜡笔小新 2024-12-25 16:03:57
本文介绍了解决局域网内SSH连接到服务器时出现长时间等待问题的方法。通过调整配置和优化网络设置,可以显著缩短SSH连接的时间。 ...
[详细]
蜡笔小新 2024-12-25 11:31:48
本文详细探讨了 org.apache.hadoop.ha.HAServiceTarget 类中的 checkFencingConfigured 方法,包括其功能、应用场景及代码示例。通过实际代码片段,帮助开发者更好地理解和使用该方法。 ...
[详细]
蜡笔小新 2024-12-22 18:28:35
本文探讨了Java项目中应用分层的最佳实践,不仅介绍了常见的三层架构(Controller、Service、DAO),还深入分析了各层的职责划分及优化建议。通过合理的分层设计,可以提高代码的可维护性、扩展性和团队协作效率。 ...
[详细]
蜡笔小新 2024-12-22 12:14:24
本文详细介绍了Java中org.w3c.dom.Text类的splitText()方法,通过多个代码示例展示了其实际应用。该方法用于将文本节点在指定位置拆分为两个节点,并保持在文档树中。 ...
[详细]
蜡笔小新 2024-12-26 18:31:42
阿里云ecs怎么配置php环境,阿里云ecs配置选择 ...
[详细]
蜡笔小新 2024-12-23 11:12:07
本文详细探讨了SpringMVC的核心组件——DispatcherServlet的运作机制,旨在帮助有一定Java和Spring基础的开发人员理解HTTP请求是如何被映射到Controller并执行的。文章将解答以下问题:1. HTTP请求如何映射到Controller;2. Controller是如何被执行的。 ...
[详细]
蜡笔小新 2024-12-21 18:50:52