当前位置:首页 > 后端开发 > 正文

java里怎么调用数据库

在 Java 中通过 JDBC 调用数据库:先加载驱动类,用 DriverManager 获取连接;再创建 Statement 对象,执行 SQL 语句;最后处理结果集

以下是关于 Java 调用数据库 的完整技术指南,涵盖核心步骤、最佳实践及典型场景实现:

java里怎么调用数据库 第1张

前置准备与核心依赖

1 必备组件清单

类别 名称/描述 作用说明
JDBC驱动 mysql-connector-java.jar MySQL官方提供的Java数据库连接器
项目配置文件 jdbc.properties 存储数据库连接参数(如URL/账号/密码)
Java核心API java.sql. 提供标准数据库操作接口
IDE工具链 Maven/Gradle + IntelliJ IDEA 项目管理与代码调试支持

2 环境配置要点

  • Maven依赖声明(以MySQL为例): <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency>
  • 属性文件内容示例 (src/main/resources/jdbc.properties): db.url=jdbc:mysql://localhost:3306/mydatabase?useSSL=false&serverTimezone=UTC db.user=root db.password=123456


标准开发流程详解

1 五步法实现数据库交互

序号 阶段 关键技术点 注意事项
1 加载数据库驱动 Class.forName("com.mysql.cj.jdbc.Driver") 仅适用于传统方式,新版JDBC可省略此步
2 建立数据库连接 DriverManager.getConnection(url, user, password) 必传三要素:URL/用户名/密码
3 创建执行器对象 Connection.createStatement() → 普通语句

prepareStatement(sql) → 预编译语句

优先使用PreparedStatement防SQL载入
4 执行SQL指令 executeUpdate()→更新操作

executeQuery()→查询操作

根据业务类型选择对应方法
5 处理结果集 ResultSet遍历+next()判断+getXXX()取值 严格遵循列索引/别名映射规则
6 资源释放 close()顺序:ResultSet→Statement→Connection 必须放在finally块保证执行

2 完整代码示例(增删改查全场景)

import java.sql.; import java.util.Properties; public class JdbcDemo { // 静态常量定义 private static final String PROPERTIES_PATH = "jdbc.properties"; public static void main(String[] args) { // 1. 读取配置文件 Properties prop = new Properties(); try { prop.load(Thread.currentThread().getContextClassLoader().getResourceAsStream(PROPERTIES_PATH)); } catch (Exception e) { System.err.println("配置文件加载失败: " + e.getMessage()); return; } // 2. 声明数据库连接变量 Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; try { // 3. 建立数据库连接 conn = DriverManager.getConnection( prop.getProperty("db.url"), prop.getProperty("db.user"), prop.getProperty("db.password") ); // ========== 插入数据示例 ========== String insertSql = "INSERT INTO users(name, email) VALUES(?, ?)"; pstmt = conn.prepareStatement(insertSql); pstmt.setString(1, "张三"); pstmt.setString(2, "zhangsan@example.com"); int affectedRows = pstmt.executeUpdate(); System.out.println("插入成功,影响行数: " + affectedRows); // ========== 查询数据示例 ========== String selectSql = "SELECT id, name, email FROM users WHERE id = ?"; pstmt = conn.prepareStatement(selectSql); pstmt.setInt(1, 1); // 假设刚插入的ID为1 rs = pstmt.executeQuery(); while(rs.next()) { int id = rs.getInt("id"); String name = rs.getString("name"); String email = rs.getString("email"); System.out.printf("查询结果 ID:%d, 姓名:%s, 邮箱:%s%n", id, name, email); } // ========== 更新数据示例 ========== String updateSql = "UPDATE users SET email=? WHERE id=?"; pstmt = conn.prepareStatement(updateSql); pstmt.setString(1, "new_email@example.com"); pstmt.setInt(2, 1); affectedRows = pstmt.executeUpdate(); System.out.println("更新成功,影响行数: " + affectedRows); // ========== 删除数据示例 ========== String deleteSql = "DELETE FROM users WHERE id=?"; pstmt = conn.prepareStatement(deleteSql); pstmt.setInt(1, 1); affectedRows = pstmt.executeUpdate(); System.out.println("删除成功,影响行数: " + affectedRows); } catch (SQLException e) { System.err.println("数据库操作异常: " + e.getMessage()); e.printStackTrace(); } finally { // 4. 逆向关闭资源 try { if(rs != null) rs.close(); } catch(SQLException ignored) {} try { if(pstmt != null) pstmt.close(); } catch(SQLException ignored) {} try { if(conn != null) conn.close(); } catch(SQLException ignored) {} } } }

3 关键机制解析

技术点 实现原理 优势分析
预编译语句(占位符) SQL模板预先编译,参数化绑定 防止SQL载入

提升重复执行效率

事务控制 conn.setAutoCommit(false) + commit()/rollback() 保证原子性操作

批量操作一致性

批处理 addBatch() + executeBatch() ⏱️ 减少网络往返次数

⏱️ 提升大数据量性能

连接池 HikariCP/C3P0/DBCP等第三方库 复用物理连接

降低建连开销


进阶优化策略

1 连接池选型对比表

连接池名称 特点 适用场景
HikariCP 轻量级/高性能/零配置启动 中小型应用首选
C3P0 功能丰富/支持缓存/JMX监控 复杂企业级系统
DBCP Apache Commons组件/简单易用 快速原型开发
Druid 阿里开源/监控功能强大/支持SQL防火墙 高并发生产环境

2 性能调优建议

  1. 索引优化:对高频查询字段建立复合索引
  2. 分页查询:使用LIMIT startIndex, pageSize替代全表扫描
  3. 懒加载:仅在需要时初始化数据库连接
  4. 超时设置:jdbc:mysql://...?connectTimeout=5000&socketTimeout=10000
  5. 二进制日志:开启binlog用于主从复制和故障恢复


常见错误解决方案

错误现象 根本原因 解决方法
Communications link failure 网络中断/数据库服务未启动 检查防火墙/重启数据库服务
Access denied for user 用户名密码错误/权限不足 核对凭证/授予相应权限
Table doesn't exist 表名大小写不匹配/未创建表 统一使用反引号`table_name`
Too many connections 连接数超过最大限制 增大maxPoolSize或优化业务逻辑
Lock wait timeout exceeded 长事务导致锁竞争 缩短事务时长/优化锁粒度


相关问答FAQs

Q1: 如何有效防止SQL载入攻破?

A: 应始终使用PreparedStatement代替字符串拼接的Statement,通过占位符进行参数化绑定,JDBC驱动会自动对特殊字符进行转义。

java里怎么调用数据库 第2张

java里怎么调用数据库 第3张

// 危险做法(易受载入) String sql = "SELECT FROM users WHERE username='" + userInput + "'"; // 安全做法(推荐) String sql = "SELECT FROM users WHERE username=?"; PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setString(1, userInput);

Q2: 为什么要按照ResultSet→Statement→Connection的顺序关闭资源?

A: 因为这三个对象存在依赖关系:ResultSet依赖于Statement,Statement又依赖于Connection,如果先关闭父级对象(如Connection),子级对象(如ResultSet)会立即失效,反向关闭可以确保所有资源都被正确释放,避免内存泄漏,典型的finally块结构如下:

finally { try { if(rs != null) rs.close(); } catch(SQLException ignored) {} try { if(pstmt != null) pstmt.close(); } catch(SQLException ignored) {} try { if(conn != null) conn.close(); } catch(SQLException ignored) {}

0