Java SQL数据库编程实战:从基础连接到高级事务处理

2024-06-21 超腾开源 277 次阅读 0 次点赞
本文深入讲解Java.sql包的核心功能,详细介绍了Connection、Statement、PreparedStatement、ResultSet等关键接口的使用方法。通过完整的代码示例展示了数据库连接建立、SQL查询执行、事务管理、批量操作等实际应用场景,特别强调了使用PreparedStatement防止SQL注入的最佳实践,以及try-with-resources进行资源自动管理的重要性。

Java.sql包是Java标准库中用于数据库连接和操作的核心API,它提供了一系列接口和类来实现与关系型数据库的连接、SQL语句执行、事务管理和结果集处理等功能。

主要类和接口

1. 核心接口

1、Connection - 数据库连接

2、Statement - 执行静态SQL语句

3、PreparedStatement - 执行预编译SQL语句

4、CallableStatement - 执行存储过程

5、ResultSet - 查询结果集

6、DatabaseMetaData - 数据库元数据

2. 驱动管理

  • DriverManager - 管理数据库驱动程序

3. 数据类型

  • Types - 定义SQL数据类型常量

示例代码

1. 基础数据库连接和查询

import java.sql.*;

public class BasicJDBCExample {
    // 数据库连接信息
    private static final String URL = "jdbc:mysql://localhost:3306/testdb";
    private static final String USER = "username";
    private static final String PASSWORD = "password";
    
    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        
        try {
            // 1. 注册驱动 (新版本JDBC可以自动加载)
            Class.forName("com.mysql.cj.jdbc.Driver");
            
            // 2. 建立连接
            conn = DriverManager.getConnection(URL, USER, PASSWORD);
            System.out.println("数据库连接成功!");
            
            // 3. 创建Statement对象
            stmt = conn.createStatement();
            
            // 4. 执行查询
            String sql = "SELECT id, name, email FROM users";
            rs = stmt.executeQuery(sql);
            
            // 5. 处理结果集
            while (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                String email = rs.getString("email");
                
                System.out.printf("ID: %d, Name: %s, Email: %s%n", 
                                 id, name, email);
            }
            
        } catch (ClassNotFoundException e) {
            System.err.println("找不到数据库驱动: " + e.getMessage());
        } catch (SQLException e) {
            System.err.println("数据库操作错误: " + e.getMessage());
        } finally {
            // 6. 关闭资源
            try {
                if (rs != null) rs.close();
                if (stmt != null) stmt.close();
                if (conn != null) conn.close();
            } catch (SQLException e) {
                System.err.println("关闭资源错误: " + e.getMessage());
            }
        }
    }
}

2. 使用PreparedStatement防止SQL注入

import java.sql.*;

public class PreparedStatementExample {
    private static final String URL = "jdbc:mysql://localhost:3306/testdb";
    private static final String USER = "username";
    private static final String PASSWORD = "password";
    
    public static void main(String[] args) {
        try (Connection conn = DriverManager.getConnection(URL, USER, PASSWORD)) {
            
            // 插入数据
            insertUser(conn, "张三", "zhangsan@example.com");
            
            // 查询数据
            findUserByName(conn, "张三");
            
            // 更新数据
            updateUserEmail(conn, "张三", "new_email@example.com");
            
            // 删除数据
            deleteUser(conn, "张三");
            
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    
    // 插入用户
    public static void insertUser(Connection conn, String name, String email) 
            throws SQLException {
        String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
        
        try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setString(1, name);
            pstmt.setString(2, email);
            
            int rows = pstmt.executeUpdate();
            System.out.println("插入了 " + rows + " 行数据");
        }
    }
    
    // 根据姓名查询用户
    public static void findUserByName(Connection conn, String name) 
            throws SQLException {
        String sql = "SELECT id, name, email FROM users WHERE name = ?";
        
        try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setString(1, name);
            
            try (ResultSet rs = pstmt.executeQuery()) {
                while (rs.next()) {
                    System.out.printf("找到用户: ID=%d, Name=%s, Email=%s%n",
                            rs.getInt("id"), 
                            rs.getString("name"), 
                            rs.getString("email"));
                }
            }
        }
    }
    
    // 更新用户邮箱
    public static void updateUserEmail(Connection conn, String name, String newEmail) 
            throws SQLException {
        String sql = "UPDATE users SET email = ? WHERE name = ?";
        
        try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setString(1, newEmail);
            pstmt.setString(2, name);
            
            int rows = pstmt.executeUpdate();
            System.out.println("更新了 " + rows + " 行数据");
        }
    }
    
    // 删除用户
    public static void deleteUser(Connection conn, String name) 
            throws SQLException {
        String sql = "DELETE FROM users WHERE name = ?";
        
        try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setString(1, name);
            
            int rows = pstmt.executeUpdate();
            System.out.println("删除了 " + rows + " 行数据");
        }
    }
}

3. 事务管理示例

import java.sql.*;

public class TransactionExample {
    private static final String URL = "jdbc:mysql://localhost:3306/testdb";
    private static final String USER = "username";
    private static final String PASSWORD = "password";
    
    public static void main(String[] args) {
        try (Connection conn = DriverManager.getConnection(URL, USER, PASSWORD)) {
            // 关闭自动提交,开启事务
            conn.setAutoCommit(false);
            
            try {
                // 执行多个数据库操作
                transferMoney(conn, 1, 2, 100.0);
                
                // 提交事务
                conn.commit();
                System.out.println("事务提交成功!");
                
            } catch (SQLException e) {
                // 回滚事务
                conn.rollback();
                System.err.println("事务回滚: " + e.getMessage());
            } finally {
                // 恢复自动提交
                conn.setAutoCommit(true);
            }
            
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    
    // 转账操作
    public static void transferMoney(Connection conn, int fromAccount, 
                                    int toAccount, double amount) 
            throws SQLException {
        // 扣款
        String deductSQL = "UPDATE accounts SET balance = balance - ? WHERE id = ?";
        try (PreparedStatement pstmt = conn.prepareStatement(deductSQL)) {
            pstmt.setDouble(1, amount);
            pstmt.setInt(2, fromAccount);
            pstmt.executeUpdate();
        }
        
        // 检查余额是否足够
        String checkBalanceSQL = "SELECT balance FROM accounts WHERE id = ?";
        try (PreparedStatement pstmt = conn.prepareStatement(checkBalanceSQL)) {
            pstmt.setInt(1, fromAccount);
            try (ResultSet rs = pstmt.executeQuery()) {
                if (rs.next() && rs.getDouble("balance") < 0) {
                    throw new SQLException("余额不足");
                }
            }
        }
        
        // 存款
        String addSQL = "UPDATE accounts SET balance = balance + ? WHERE id = ?";
        try (PreparedStatement pstmt = conn.prepareStatement(addSQL)) {
            pstmt.setDouble(1, amount);
            pstmt.setInt(2, toAccount);
            pstmt.executeUpdate();
        }
    }
}

4. 批量操作示例

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class BatchOperationExample {
    private static final String URL = "jdbc:mysql://localhost:3306/testdb";
    private static final String USER = "username";
    private static final String PASSWORD = "password";
    
    public static void main(String[] args) {
        List<User> users = new ArrayList<>();
        users.add(new User("李四", "lisi@example.com"));
        users.add(new User("王五", "wangwu@example.com"));
        users.add(new User("赵六", "zhaoliu@example.com"));
        
        batchInsertUsers(users);
    }
    
    public static void batchInsertUsers(List<User> users) {
        String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
        
        try (Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            
            // 关闭自动提交以提高性能
            conn.setAutoCommit(false);
            
            for (User user : users) {
                pstmt.setString(1, user.getName());
                pstmt.setString(2, user.getEmail());
                pstmt.addBatch(); // 添加到批处理
            }
            
            // 执行批处理
            int[] results = pstmt.executeBatch();
            conn.commit();
            
            System.out.println("批量插入完成,影响了 " + results.length + " 行");
            
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    
    static class User {
        private String name;
        private String email;
        
        public User(String name, String email) {
            this.name = name;
            this.email = email;
        }
        
        public String getName() { return name; }
        public String getEmail() { return email; }
    }
}

注意事项

1、资源管理: 使用try-with-resources语句自动关闭连接,避免资源泄漏

2、SQL注入: 始终使用PreparedStatement而不是字符串拼接来构建SQL

3、事务管理: 合理使用事务确保数据一致性

4、连接池: 在生产环境中使用连接池管理数据库连接

5、异常处理: 妥善处理SQLException,记录适当的错误信息

这些示例展示了java.sql包的基本用法,实际开发中通常会结合连接池和更复杂的错误处理机制。

最后更新于6月前
本文由人工编写,AI优化,转载请注明原文地址: java.sql使用方法及代码示例

评论 (1)

登录 后发表评论

暗夜骑士暗夜骑士2025-11-17 10:38:33

非常实用的Java数据库操作指南!示例代码很清晰,对理解JDBC核心接口帮助很大。感谢作者分享!