drivermanager.getconnection() 连不上数据库主因是url参数缺失(如usessl=false、servertimezone=utc)、数据库名拼错、端口被拦或mysql未启动;jdk 6+后无需class.forname();应优先用preparedstatement防sql注入;connection线程不安全,须按事务边界严格管理生命周期。

DriverManager.getConnection() 为什么连不上数据库
不是 URL 写错就是驱动没加载,但 JDK 6+ 后者基本自动了,真正卡住的往往是 jdbc:mysql://localhost:3306/mydb 这类 URL 缺少必要参数。
-
useSSL=false:MySQL 8.0+ 默认强制 SSL,不加这个会报Communications link failure -
serverTimezone=UTC:时区不匹配导致java.sql.SQLException: The server time zone value '...' is unrecognized - URL 中数据库名拼错、端口被防火墙拦住、MySQL 服务根本没起来——这些比代码逻辑更容易漏查
JDBC 驱动类名和 Class.forName() 还需手动调用吗
JDK 6 开始,DriverManager 通过 ServiceLoader 自动扫描 META-INF/services/java.sql.Driver,只要驱动 JAR 在 classpath,Class.forName("com.mysql.cj.jdbc.Driver") 就纯属冗余。
- MySQL 5.x 驱动类名是
com.mysql.jdbc.Driver,8.x 是com.mysql.cj.jdbc.Driver,混用会抛ClassNotFoundException - Spring Boot 等框架默认启用自动注册,手写
Class.forName()反而可能触发重复加载警告 - 真要兼容老环境(JDK 5),才需要显式调用;否则删掉更干净
Connection.createStatement() 和 prepareStatement() 到底该选谁
除非你拼接 SQL 字符串执行 DDL(比如 "CREATE TABLE " + tableName),否则一律用 prepareStatement()。
-
createStatement()无法防 SQL 注入,参数全靠字符串拼接,"WHERE id = " + userInput是典型雷区 -
prepareStatement()的预编译在多数数据库里是真预编译(MySQL 5.7+ 默认开启useServerPrepStmts=true),性能和安全双收益 - 注意
setString(1, null)会报空指针,得用setNull(1, Types.VARCHAR)
DriverManager.getConnection() 返回的 Connection 是线程安全的吗
完全不安全。同一个 Connection 实例被多个线程并发调用 executeQuery() 或 close(),轻则抛 SQLException: Operation not allowed after ResultSet closed,重则连接状态错乱、事务失效。
立即学习“Java免费学习笔记(深入)”;
- Web 应用里,每个 HTTP 请求应独占一个
Connection,用完立刻close() - 别把
Connection存成静态变量或单例,也别在线程池里复用未清理的连接 - HikariCP、Druid 这些连接池返回的
Connection是代理对象,本身线程不安全,但池管理保证了“每次获取都是可用新实例”
最常被忽略的是:事务边界和连接生命周期必须严格对齐。一个 Connection 上开启事务后,所有操作必须用它,不能中途换连接,也不能跨线程传——这点比语法细节更致命。










