JDBC 基础
连接、语句与结果集
JDBC 基础 是 CoddyKit 上的免费 Java Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。
什么是 JDBC?
JDBC(Java 数据库连接)是从 Java 访问关系型数据库的标准应用程序接口。
- 它位于
java.sql包中。 - 每种数据库都会提供一个实现 JDBC 接口的驱动程序。
- 您应针对
Connection、Statement和ResultSet等接口编写代码,而不是直接针对供应商类编写代码。
借助这一抽象,同一份代码就能用于 PostgreSQL、MySQL、H2 或 Oracle。
核心接口
三个接口承担了大部分工作:
Connection——与数据库建立的开放会话。Statement/PreparedStatement——发送 SQL。ResultSet——用于遍历查询返回行的游标。
您可以从 DriverManager 或 DataSource 获取 Connection。
打开连接
DriverManager.getConnection(url, user, password) 返回一个活动的 Connection。
JDBC 连接地址用于标识数据库,例如 jdbc:postgresql://localhost:5432/shop。现代驱动程序会自动注册自身,因此您不再需要调用 Class.forName(...)。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Main {
public static void main(String[] args) {
String url = "jdbc:postgresql://localhost:5432/shop";
try (Connection conn = DriverManager.getConnection(url, "app", "secret")) {
System.out.println("Connected: " + !conn.isClosed());
} catch (SQLException e) {
System.out.println("Connection failed: " + e.getMessage());
}
}
}资源自动管理
Connection、Statement 和 ResultSet 都实现了 AutoCloseable。
请始终将它们放在资源自动管理代码块中,这样即使抛出异常,它们也会自动关闭。连接泄漏会迅速耗尽数据库连接。
- 资源会按照相反的顺序关闭。
- 不需要
finally代码块。
运行查询
对于简单的 SELECT,请创建一个 Statement 并调用 executeQuery,它会返回一个 ResultSet。
示例使用内存模拟,因此您无需连接真实数据库也能看到完整流程。在生产环境中,SQL 会针对该连接执行。
import java.util.List;
public class Main {
public static void main(String[] args) {
// Simulated result of: SELECT name FROM users
List<String> names = List.of("Ada", "Linus", "Grace");
System.out.println("Query returned " + names.size() + " rows:");
for (String name : names) {
System.out.println(" - " + name);
}
}
}读取 ResultSet
ResultSet 初始位置在第一行之前。请在循环中调用 rs.next();没有更多行时,它会返回 false。
您可以通过列名或从 1 开始的索引,使用类型化读取方法读取列:
rs.getInt("id")rs.getString("name")rs.getDouble("price")
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Main {
public static void main(String[] args) {
String url = "jdbc:postgresql://localhost:5432/shop";
try (Connection conn = DriverManager.getConnection(url, "app", "secret");
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT id, name FROM users")) {
while (rs.next()) {
System.out.println(rs.getInt("id") + ": " + rs.getString("name"));
}
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
}用于写入的 executeUpdate
对于 INSERT、UPDATE 和 DELETE,请使用 executeUpdate。它会返回一个 int,表示受影响的行数。
只有在您事先不知道语句是否会返回结果集时,才使用 execute。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class Main {
public static void main(String[] args) {
String url = "jdbc:postgresql://localhost:5432/shop";
try (Connection conn = DriverManager.getConnection(url, "app", "secret");
Statement st = conn.createStatement()) {
int rows = st.executeUpdate("DELETE FROM sessions WHERE expired = true");
System.out.println("Deleted " + rows + " rows");
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
}将行映射为对象
大多数应用程序都会将每一行转换为一个领域对象。请遍历 ResultSet 并构建对象实例。
下面是这种模式的示例,经过模拟后可以独立运行。使用 record 可以简洁地完成映射。
import java.util.ArrayList;
import java.util.List;
public class Main {
record User(int id, String name) {}
public static void main(String[] args) {
// Stand-in for iterating a ResultSet
String[][] rows = {{"1", "Ada"}, {"2", "Linus"}};
List<User> users = new ArrayList<>();
for (String[] row : rows) {
users.add(new User(Integer.parseInt(row[0]), row[1]));
}
users.forEach(System.out::println);
}
}处理 SQLException
几乎所有 JDBC 方法都会抛出受检查异常 SQLException。
它包含有用的诊断信息:
getMessage()——面向用户的可读文本。getSQLState()——标准的 5 个字符状态代码。getErrorCode()——供应商特定的代码。
请记录这些信息,不要将异常吞掉。
import java.sql.SQLException;
public class Main {
public static void main(String[] args) {
SQLException e = new SQLException("duplicate key", "23505", 7);
System.out.println("Message: " + e.getMessage());
System.out.println("SQLState: " + e.getSQLState());
System.out.println("ErrorCode: " + e.getErrorCode());
}
}DatabaseMetaData
conn.getMetaData() 返回一个描述数据库本身的 DatabaseMetaData 对象。
它可以告诉您产品名称和版本、支持的功能,甚至列出表和列。这就是架构浏览器等工具无需硬编码供应商细节便能工作的方式。
整合起来
典型的读取流程如下:
- 在资源自动管理代码块中打开
Connection。 - 创建一个
Statement(或者更好的选择是PreparedStatement)。 - 调用
executeQuery,并使用rs.next()循环读取。 - 将列映射到对象中。
- 让资源自动管理机制关闭所有资源。
下一课将让查询能够抵御注入攻击。
快速检查
Statement.executeUpdate 会返回什么?
回顾
现在您已经了解 JDBC 的核心流程:
DriverManager.getConnection会打开一个Connection。Statement发送 SQL;executeQuery返回ResultSet,executeUpdate返回受影响的行数。- 使用
rs.next()和类型化读取方法进行迭代。 - 始终使用资源自动管理,并结合其状态和错误代码处理
SQLException。
常见问题解答
「JDBC 基础」课时是免费的吗?
是的 — 「JDBC 基础」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。
「JDBC 基础」这节课中我会学到什么?
连接、语句与结果集 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Java Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「JDBC 基础」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Java Academy 课中编写并运行代码吗?
能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。