当前位置:首页 > 数据库 > 正文

java查询数据库的代码怎么写

va用JDBC连接 数据库,先加载驱动、建连接,再创Statement对象执行SQL查询

核心开发流程解析

  1. 加载驱动类

    必须通过Class.forName()显式注册JDBC驱动(如MySQL需使用com.mysql.cj.jdbc.Driver),现代JDBC4+虽支持自动加载,但显式声明可避免版本兼容性问题。

    Class.forName("com.mysql.cj.jdbc.Driver"); // 适用于MySQL Connector/J 8.0+
  2. 建立连接对象

    使用DriverManager.getConnection()传入三要素:URL格式为协议://主机:端口/数据库名?参数键=值,典型配置包括:

    • useSSL=false禁用安全连接(本地测试常用)
    • serverTimezone=UTC解决时区异常
    • characterEncoding=UTF-8确保中文正常传输

      示例代码:

      java查询数据库的代码怎么写 第1张

      String url = "jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC&characterEncoding=utf8"; Connection conn = DriverManager.getConnection(url, "username", "password");
  3. 创建Statement执行体

    推荐采用预编译语句(PreparedStatement)防止SQL载入攻破,其优势在于:

    • 占位符动态绑定参数,自动处理特殊字符转义
    • 数据库预编译优化提升多次执行效率

      基本用法: String sql = "SELECT id, name FROM users WHERE age > ? AND city = ?"; PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setInt(1, 18); // 第一个问号替换为整数 pstmt.setString(2, "北京"); // 第二个问号替换为字符串

  4. 结果集遍历规范

    遵循while(rs.next())循环逐行读取数据,注意列索引从1开始,建议优先获取列名再取值以保证可读性:

    java查询数据库的代码怎么写 第2张

    ResultSetMetaData metaData = rs.getMetaData(); int columnCount = metaData.getColumnCount(); for (int i = 1; i <= columnCount; i++) { System.out.printf("%-15s", metaData.getColumnName(i)); // 打印表头 } while (rs.next()) { for (int i = 1; i <= columnCount; i++) { Object val = rs.getObject(i); System.out.printf("%-15s", val != null ? val.toString() : "NULL"); } System.out.println(); // 换行分隔记录 }
  5. 资源释放顺序

    严格按创建逆序关闭资源(ResultSet→Statement→Connection),且每个close操作都应放在finally块或try-with-resources中,遗漏任一环节都会导致连接泄漏。


完整代码实现(含异常处理)

import java.sql.; import javax.xml.bind.DatatypeConverter; // 用于Base64编码调试可选 public class JdbcDemo { private static final String DB_URL = "jdbc:mysql://localhost:3306/testdb"; private static final String USERNAME = "root"; private static final String PASSWORD = "your_password"; public static void main(String[] args) { Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; try { // Step 1: 注册驱动(JDBC4+可省略但建议保留) Class.forName("com.mysql.cj.jdbc.Driver"); // Step 2: 获取数据库连接 connection = DriverManager.getConnection(DB_URL, USERNAME, PASSWORD); System.out.println(" 成功连接到数据库"); // Step 3: 构建带参数的SQL查询 String query = "SELECT product_id, product_name, unit_price FROM products WHERE category_id = ?"; preparedStatement = connection.prepareStatement(query); preparedStatement.setInt(1, 5); // 设置电子品类ID过滤条件 // Step 4: 执行查询并获取结果集 resultSet = preparedStatement.executeQuery(); // Step 5: 处理结果数据 System.out.println("n 商品列表:"); printTableHeader(resultSet); // 打印列标题行 while (resultSet.next()) { int id = resultSet.getInt("product_id"); String name = resultSet.getString("product_name"); double price = resultSet.getDouble("unit_price"); System.out.printf("| %-6d | %-20s | %10.2f 元|n", id, name, price); } } catch (ClassNotFoundException e) { System.err.println(" 未找到JDBC驱动程序!请检查依赖库是否包含mysql-connector-java-x.x.xx.jar"); e.printStackTrace(); } catch (SQLException e) { System.err.println("️ SQL执行错误:" + e.getMessage()); if (e.getErrorCode() == 1062) { // Duplicate entry示例处理 System.err.println(" 唯一约束冲突,插入失败"); } else { e.printStackTrace(); } } finally { // Step 6: 确保资源被正确释放 closeQuietly(resultSet); closeQuietly(preparedStatement); closeQuietly(connection); } } // 辅助方法:静默关闭资源避免二次异常 private static void closeQuietly(AutoCloseable resource) { if (resource != null) { try { resource.close(); } catch (Exception ignored) { / NOP / } } } // 辅助方法:根据ResultSet元数据生成表格头部 private static void printTableHeader(ResultSet rs) throws SQLException { ResultSetMetaData meta = rs.getMetaData(); int cols = meta.getColumnCount(); StringBuilder headerLine = new StringBuilder("+"); for (int i = 0; i < cols; i++) { headerLine.append("-------------+"); } System.out.println(headerLine); for (int i = 1; i <= cols; i++) { String colName = meta.getColumnLabel(i); // 优先使用别名,否则用原名 System.out.printf("| %-15s ", colName); } System.out.println("|"); System.out.println(headerLine); } }


关键注意事项清单

风险点 解决方案 示例代码片段
SQL载入漏洞 永远使用PreparedStatement替代Statement pstmt.setString(index, value)
连接池未配置 生产环境务必使用HikariCP等连接池组件 Maven依赖:HikariCP
字符编码不一致 URL中指定characterEncoding参数,建表时设置CHARACTER SET utf8mb4 jdbc:...&characterEncoding=utf8
批量操作性能低下 addBatch()+executeBatch()组合实现高效批处理 batchSize>50时效果显著
事务未提交回滚 显式开启事务后需commit/rollback,默认自动提交模式不适合复杂业务逻辑 conn.setAutoCommit(false);
大结果集内存溢出 启用流式读取模式(setFetchSize)或分页查询 rs.setFetchSize(Integer.MIN_VALUE);


扩展实践建议

  1. ORM框架集成

    当项目规模扩大时,推荐迁移至MyBatis或Hibernate等ORM框架,以MyBatis为例,XML映射文件可实现对象关系自动转换:

    java查询数据库的代码怎么写 第3张

    <select id="listProductsByCategory" resultType="com.example.Product"> SELECT FROM products WHERE category_id = #{categoryId} </select>
  2. Druid监控面板

    接入阿里巴巴开源的Druid监控组件,实时查看SQL执行情况、慢查询日志和连接池状态:

    DruidDataSource dataSource = new DruidDataSource(); dataSource.setUrl(DB_URL); dataSource.setUsername(USERNAME); dataSource.setPassword(PASSWORD); // 配置监控统计过滤器...
  3. 分布式事务解决方案

    微服务架构下采用Seata中间件保证跨库事务一致性,通过注解方式声明全局事务边界:

    @GlobalTransactional(timeoutMillis = 300000) public void placeOrder() { // 调用多个服务的数据库操作 }


FAQs

Q1: Java程序连接MySQL时报“Communications link failure”如何解决?

原因分析:通常是由于网络不通、防火墙拦截或MySQL服务未启动导致。

排查步骤

① 使用telnet命令测试端口连通性:telnet localhost 3306

② 检查防火墙设置(Linux系统执行sudo ufw allow 3306/tcp)

③ 确认MySQL配置文件中的bind-address不是仅限本地访问(改为0.0.0允许外部连接)

④ 验证用户权限是否包含远程登录权限(GRANT ALL PRIVILEGES ON TO ‘user’@’%’ IDENTIFIED BY ‘pass’;)

Q2: 执行UPDATE语句后受影响行数如何获取?

实现方法:调用executeUpdate()返回值为int类型,表示实际更新的记录数量,典型用法如下:

String updateSql = "UPDATE accounts SET balance = balance ? WHERE user_id = ?"; PreparedStatement pstmt = conn.prepareStatement(updateSql); pstmt.setBigDecimal(1, new BigDecimal("100.00")); pstmt.setInt(2, targetUserId); int affectedRows = pstmt.executeUpdate(); // 获取影响行数 if (affectedRows == 0) { throw new RuntimeException("账户扣款失败,用户不存在或余额不足

0