
本文介绍在 java jdbc 应用中,如何将 mysql 表中的所有用户数据封装为对象并存入 list(如 arraylist 或 linkedlist),再统一打印输出,替代直接在 resultset 循环中打印的原始方式。
在实际开发中,将数据库查询结果“加载到内存集合”是常见需求——它不仅便于后续业务逻辑处理(如排序、过滤、分页),也符合分层设计原则:数据访问层负责获取数据,业务层负责操作数据。相比直接在 while(rs.next()) 中打印,将记录转为对象列表再输出,代码更清晰、可维护性更高,也更容易单元测试。
核心思路:面向对象封装 + 集合存储
关键在于两点:
- 定义数据载体类(推荐使用 Java 14+ 的 record,简洁安全);
- 遍历 ResultSet,逐条构造对象并添加至 List;
- 关闭资源后,再对 List 进行统一操作(如打印)。
以下是一个完整、可运行的示例(基于你的原始代码优化):
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class JDBC {
// 使用 record 封装单条学生记录(Java 14+ 支持)
// 编译器自动提供构造方法、getter、equals、hashCode 和 toString
record Student(String name, int contact, int age) {
@Override
public String toString() {
return String.format("Student{name='%s', contact=%d, age=%d}", name, contact, age);
}
}
public static void main(String[] args) {
Connection con = null;
Statement st = null;
ResultSet rs = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
con = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/mydatabase?useSSL=false&serverTimezone=UTC",
"root", "root"
);
st = con.createStatement();
rs = st.executeQuery("SELECT name, contact, age FROM student"); // 显式列名更健壮
List students = new ArrayList<>(); // 推荐 ArrayList(随机访问多时更高效)
while (rs.next()) {
students.add(new Student(
rs.getString("name"),
rs.getInt("contact"),
rs.getInt("age")
));
}
// ✅ 所有数据已加载完成,此时关闭资源
rs.close();
st.close();
con.close();
// 统一打印(也可用于其他操作:filter、stream 处理等)
System.out.println("=== 共查询到 " + students.size() + " 条用户记录 ===");
students.forEach(System.out::println);
} catch (ClassNotFoundException | SQLException e) {
System.err.println("数据库操作异常:" + e.getMessage());
e.printStackTrace();
} finally {
// 确保资源释放(生产环境建议使用 try-with-resources)
closeQuietly(rs, st, con);
}
}
// 辅助方法:静默关闭 JDBC 资源
private static void closeQuietly(AutoCloseable... resources) {
for (AutoCloseable resource : resources) {
if (resource != null) {
try {
resource.close();
} catch (Exception ignored) {}
}
}
}
} 注意事项与最佳实践
- ✅ 优先使用 try-with-resources:现代 JDBC 编程强烈推荐,可自动关闭资源,避免泄漏(本例为兼容性暂用 finally,实际项目请改写为 try (Connection c = ...; Statement s = ...; ResultSet r = ...) { ... })。
- ✅ 显式指定查询字段:避免 SELECT *,防止表结构变更导致 rs.getInt("age") 因列序偏移而报错。
- ✅ 字段空值处理:rs.getString() 对 NULL 返回 null,若业务不允许空值,建议在 Student 构造前校验(如 Objects.requireNonNull(rs.getString("name")))。
- ⚠️ LinkedList vs ArrayList:原文提到 LinkedList “更适合逐个添加”,但实际性能差异微小;除非需频繁首尾插入/删除,否则 ArrayList 是更通用、缓存友好的选择。
- ? 密码硬编码风险:开发阶段可接受,上线前务必通过配置文件或环境变量管理数据库凭据。
通过这种方式,你不仅实现了“存入列表再打印”的需求,更构建了可扩展的数据处理骨架——后续添加搜索、导出 Excel、生成统计报表等功能,都只需复用 List











