第九章 Java数据库编程
第二节 数据库连接与操作
概述
本节内容重点讲解Java语言中如何实现数据库的连接与操作,这是Java数据库编程的核心环节。通过本节学习,考生将掌握Java连接数据库的基本步骤、JDBC(Java Database Connectivity)的工作原理、常用的数据库操作方法(增删改查),以及相关异常处理和资源管理技巧。掌握这些内容对于通过全国计算机等级考试二级Java语言程序设计科目至关重要,同时也为实际开发中处理数据库提供坚实基础。
核心概念
- JDBC (Java Database Connectivity):Java提供的用于执行数据库操作的API,支持标准的数据库连接和SQL执行。
- DriverManager:JDBC中管理数据库驱动程序的类,负责建立数据库连接。
- Connection:表示与数据库的连接会话,用于执行SQL语句。
- Statement:用于执行静态SQL语句的接口。
- PreparedStatement:预编译的SQL语句,支持参数化查询,提升效率和安全性。
- ResultSet:存储数据库查询结果的对象,支持遍历和数据访问。
- 事务管理:确保数据库操作的原子性、一致性、隔离性和持久性(ACID原则)。
原理分析
Java数据库连接基于JDBC规范,通过加载数据库驱动,向DriverManager注册驱动实现数据库连接。执行SQL时,Statement或PreparedStatement对象发送SQL到数据库服务器,数据库执行后返回结果,Java通过ResultSet对象读取结果。数据库连接是有限资源,操作完成后必须关闭连接、语句和结果集,防止资源泄露。事务管理通过Connection对象的自动提交机制控制,确保多条SQL操作的完整性。
详细内容
1. JDBC驱动的加载与注册
Java连接数据库的第一步是加载对应数据库的驱动程序。常用的加载方式有:
Class.forName("com.mysql.cj.jdbc.Driver");
此语句动态加载MySQL数据库驱动类,触发驱动的自动注册。DriverManager根据已注册的驱动管理连接。
注意:从JDBC4.0开始,部分驱动支持自动加载,可省略此步骤,但显式加载更具兼容性。
2. 建立数据库连接
使用DriverManager的getConnection方法,传入数据库URL、用户名和密码,建立连接:
String url = "jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=UTC";
Connection conn = DriverManager.getConnection(url, "root", "password");
URL格式依赖数据库类型,常见格式为:
| 数据库类型 | URL格式 |
|---|---|
| MySQL | jdbc:mysql://host:port/database |
| Oracle | jdbc:oracle:thin:@host:port:sid |
| SQLServer | jdbc:sqlserver://host:port;databaseName=database |
3. 创建执行对象
数据库连接建立后,需要创建Statement或PreparedStatement对象执行SQL。
- Statement适合执行简单无参数的SQL语句。
- PreparedStatement适合执行带参数的SQL语句,且能防止SQL注入。
示例:
Statement stmt = conn.createStatement();
PreparedStatement pstmt = conn.prepareStatement("INSERT INTO users(name, age) VALUES(?, ?)");
4. 执行SQL语句
JDBC中执行SQL主要有三种方法:
- executeQuery():执行SELECT语句,返回ResultSet。
- executeUpdate():执行INSERT、UPDATE、DELETE语句,返回受影响行数。
- execute():执行任意SQL,返回布尔值,true表示返回结果集。
示例:
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
int count = stmt.executeUpdate("DELETE FROM users WHERE id=5");
5. 结果集处理
ResultSet对象封装了查询结果,可以通过游标遍历数据,获取列值:
while(rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age");
System.out.println(id + " " + name + " " + age);
}
注意:列名不区分大小写,也可以通过列索引访问。
6. 事务管理
默认情况下,Connection对象处于自动提交模式,每条SQL执行后自动提交。可以关闭自动提交,实现事务控制:
conn.setAutoCommit(false);
try {
//执行多条SQL
conn.commit(); //提交事务
} catch(Exception e) {
conn.rollback(); //回滚事务
}
事务确保多个相关操作要么全部成功,要么全部失败,保证数据一致性。
7. 资源关闭
避免数据库连接泄漏,必须在finally块或使用try-with-resources关闭ResultSet、Statement和Connection,关闭顺序通常为:
ResultSet -> Statement -> Connection
示例:
if(rs != null) rs.close();
if(stmt != null) stmt.close();
if(conn != null) conn.close();
实例分析
实例一:连接MySQL数据库并查询数据
背景:需要查询名为employees表中的所有员工信息。
代码示例:
public void queryEmployees() {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/company?useSSL=false&serverTimezone=UTC", "root", "password");
stmt = conn.createStatement();
rs = stmt.executeQuery("SELECT id, name, position FROM employees");
while(rs.next()) {
System.out.println(rs.getInt("id") + ", " + rs.getString("name") + ", " + rs.getString("position"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try { if(rs != null) rs.close(); } catch (Exception e) {}
try { if(stmt != null) stmt.close(); } catch (Exception e) {}
try { if(conn != null) conn.close(); } catch (Exception e) {}
}
}
分析:
- 通过Class.forName加载驱动。
- 使用DriverManager获取连接。
- 创建Statement执行SELECT语句。
- 遍历ResultSet打印结果。
- 关闭资源防止泄漏。
结论:此示例完整展示了数据库连接、查询和资源管理流程。
实例二:使用PreparedStatement插入数据
背景:向students表插入学生信息,防止SQL注入。
代码示例:
public void addStudent(String name, int age) {
String sql = "INSERT INTO students(name, age) VALUES(?, ?)";
try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/school?useSSL=false&serverTimezone=UTC", "root", "password");
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, name);
pstmt.setInt(2, age);
int rows = pstmt.executeUpdate();
System.out.println("插入了 " + rows + " 条记录");
} catch (SQLException e) {
e.printStackTrace();
}
}
分析:
- 使用PreparedStatement预编译SQL。
- 使用占位符替代参数,防止SQL注入。
- try-with-resources自动关闭资源。
结论:PreparedStatement是推荐的执行带参数SQL的方法,安全高效。
实例三:事务处理示例
背景:转账操作需要同时更新两条账户余额,使用事务保证数据一致。
代码示例:
public void transferMoney(int fromId, int toId, double amount) {
Connection conn = null;
PreparedStatement pstmt1 = null;
PreparedStatement pstmt2 = null;
try {
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/bank?useSSL=false&serverTimezone=UTC", "root", "password");
conn.setAutoCommit(false);
String sql1 = "UPDATE accounts SET balance = balance - ? WHERE id = ?";
String sql2 = "UPDATE accounts SET balance = balance + ? WHERE id = ?";
pstmt1 = conn.prepareStatement(sql1);
pstmt1.setDouble(1, amount);
pstmt1.setInt(2, fromId);
pstmt1.executeUpdate();
pstmt2 = conn.prepareStatement(sql2);
pstmt2.setDouble(1, amount);
pstmt2.setInt(2, toId);
pstmt2.executeUpdate();
conn.commit();
System.out.println("转账成功");
} catch (SQLException e) {
try {
if(conn != null) conn.rollback();
System.out.println("转账失败,事务已回滚");
} catch (SQLException ex) {
ex.printStackTrace();
}
e.printStackTrace();
} finally {
try { if(pstmt1 != null) pstmt1.close(); } catch (SQLException e) {}
try { if(pstmt2 != null) pstmt2.close(); } catch (SQLException e) {}
try { if(conn != null) conn.close(); } catch (SQLException e) {}
}
}
分析:
- 关闭自动提交,实现手动事务控制。
- 多条SQL操作在try块中执行,确保原子性。
- 异常时回滚事务,避免数据不一致。
结论:事务管理是保证数据完整性的重要技术。
常见误区
误区1:未关闭数据库连接和相关资源
- 说明:连接、语句和结果集未关闭会导致资源泄露。
- 正确做法:使用try-with-resources或finally块确保关闭。
误区2:使用Statement拼接SQL字符串,易受SQL注入攻击
- 说明:拼接字符串拼写SQL,用户输入未过滤。
- 正确做法:使用PreparedStatement并设置参数。
误区3:忽略异常处理,导致程序崩溃或数据异常
- 说明:未捕获SQLException,程序异常中断。
- 正确做法:捕获异常并妥善处理或记录日志。
误区4:不使用事务处理复杂的多条数据库操作
- 说明:多条操作中间出错,导致数据不一致。
- 正确做法:关闭自动提交,使用事务控制。
误区5:驱动加载方式混淆,导致连接失败
- 说明:忘记加载驱动或驱动版本不匹配。
- 正确做法:确认驱动包版本,正确加载驱动。
应用场景
- 企业信息管理系统:员工信息、客户关系、库存管理等模块数据存储与查询。
- 电子商务平台:用户注册、商品展示、订单处理等数据库操作。
- 银行金融系统:账户管理、交易处理,需强事务支持。
- 教学管理系统:学生信息、课程安排、成绩查询。
- 数据分析与报表系统:从数据库批量查询数据进行统计分析。
知识拓展
- 连接池技术:利用连接池复用数据库连接,提高应用性能。
- ORM框架:如Hibernate、MyBatis,简化数据库操作,支持对象关系映射。
- SQL优化:掌握索引、执行计划,提升查询效率。
- 分布式数据库:理解分布式系统中数据库的连接与事务管理。
- NoSQL数据库基础:了解非关系型数据库与JDBC的区别及应用。
总结回顾
本节全面介绍了Java中数据库连接与操作的核心内容。首先明确了JDBC及其关键接口和类,深入理解了数据库连接的建立、SQL语句执行、结果集处理和事务管理。通过多个实例展示了具体编码步骤和注意事项,帮助考生掌握实战技能。归纳了常见误区,提醒考生避免常见错误。最后介绍了实际应用场景和进一步学习方向,为后续数据库编程深入打下坚实基础。掌握本节内容,是顺利通过全国计算机等级考试二级Java语言程序设计的重要保障。
以上内容建议配合实际编程练习,加深理解和应用能力。考试复习时重点关注JDBC关键类及方法、事务控制和资源管理技巧。祝各位考生学习进步,考试顺利!