55、使用 JDBC 连接数据库:全面指南

使用 JDBC 连接数据库:全面指南

在 Java 编程中,与数据库进行交互是一项常见任务。JDBC(Java Database Connectivity)为我们提供了一种强大的方式,可以连接到几乎任何关系型数据库系统,执行 SQL 命令并处理结果。下面将详细介绍如何使用 JDBC 连接数据库、执行查询和更新操作。

1. 设置驱动程序

在编写 Java 程序通过 JDBC 访问数据库之前,需要安装一个驱动程序,将 Java 的数据库 API 类与实际数据库连接起来。有两种基本方法来设置驱动程序:使用 ODBC 或数据库连接器。

1.1 设置 ODBC 数据源

ODBC 是一种通用的数据库连接标准,几乎所有数据库程序都支持。虽然效率较低,但易于设置,适用于小型应用程序和测试。以下是为 Access 数据库创建 ODBC 数据源的步骤:
1. 打开控制面板,双击“管理工具”。
2. 双击“数据源(ODBC)”,打开“ODBC 数据源管理器”对话框。
3. 点击“系统 DSN”选项卡,然后点击“添加”。
4. 选择“Microsoft Access Driver”,然后点击“完成”。
5. 为数据源输入一个名称,此名称将在 Java 程序中用于访问数据源。
6. 点击“选择”按钮,选择要连接的数据库,然后点击“确定”。
7. 点击“确定”,将数据源添加到已配置的 ODBC 数据源列表中。
8. 点击“确定”关闭“ODBC 数据源管理器”。

1.2 设置 MySQL JDBC 连接器

数据库连接器是由数据库供应商提供的驱动程序,专门用于特定类型的数据库,比 ODBC 更高效、更强大。以下是为简单测试环境设置 MySQL JDBC 连接器的步骤:
1. 从 www.mysql.com/products/connector 下载驱动程序并解压。建议将文件解压到路径简单的文件夹,如 c:\MySql
2. 将驱动程序的 .jar 文件添加到 ClassPath 变量中。具体操作如下:
- 打开控制面板,双击“系统”。
- 点击“高级”选项卡,然后点击“环境变量”。
- 点击“新建”添加一个新的环境变量, ClassPath 变量需要指定连接器的 jar 文件的完整路径。例如,对于位于 c:\mysql 的驱动程序, ClassPath 变量可以设置为:

.;c:\mysql\mysql-connector-java-3.1.6-bin.jar
- 如果 `ClassPath` 变量已经存在,只需将连接器的 jar 文件添加到现有文本的末尾。
2. 连接到数据库

在使用 JDBC 访问 SQL 数据库之前,需要先建立与数据库的连接。步骤如下:
1. 注册驱动程序类 :使用 Class 类的 forName 方法注册驱动程序类。例如,注册 MySQL 连接器的代码如下:

try {
    Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
    System.out.println(e.getMessage());
    System.exit(0);
}
注册标准 ODBC 驱动程序的代码如下:
try {
    Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
} catch (ClassNotFoundException e) {
    System.out.println(e.getMessage());
    System.exit(0);
}
  1. 打开连接 :注册驱动程序类后,调用 DriverManager 类的静态 getConnection 方法打开连接。该方法接受三个 String 参数:数据库 URL、用户名和密码。示例代码如下:
String url = "jdbc:mysql://localhost/Movies";
String user = "root";
String pw = "pw";
try {
    con = DriverManager.getConnection(url, user, pw);
} catch (SQLException e) {
    System.out.println(e.getMessage());
    System.exit(0);
}
数据库 URL 的语法为:`jdbc:subprotocol:subname`,其中 `subprotocol` 对于 MySQL 数据库为 `mysql`,对于 ODBC 驱动程序为 `odbc`,`subname` 是数据库名称。

以下是一个返回连接到 MySQL 中 Movies 数据库的 Connection 对象的方法:

private static Connection getConnection() {
    Connection con = null;
    try {
        Class.forName("com.mysql.jdbc.Driver");
        String url = "jdbc:mysql://localhost/Movies";
        String user = "root";
        String pw = "NuttMutt";
        con = DriverManager.getConnection(url, user, pw);
    } catch (ClassNotFoundException e) {
        System.out.println(e.getMessage());
        System.exit(0);
    } catch (SQLException e) {
        System.out.println(e.getMessage());
        System.exit(0);
    }
    return con;
}
3. 查询数据库

建立与数据库的连接后,可以执行 select 语句来检索数据。需要使用几个类和接口:
- Connection :用于关闭连接和创建 Statement 对象。
- Statement :用于执行 SQL 语句并返回结果。
- ResultSet :表示查询返回的行,提供了在结果集中移动和获取列数据的方法。

以下是执行 select 语句并获取结果集的代码示例:

Statement s = con.createStatement();
String select = "Select title, year, price " + "from movie order by year";
ResultSet rows = s.executeQuery(select);
3.1 遍历结果集

ResultSet 对象包含 select 语句检索到的所有行,每次只能访问其中一行。结果集维护一个称为“游标”的指针来跟踪当前行。可以使用以下方法在结果集中移动游标:
| 方法 | 描述 |
| — | — |
| void close() | 关闭结果集 |
| void last() | 将游标移动到最后一行 |
| int getRow() | 获取当前行号 |
| boolean next() | 移动到下一行 |

以下是处理结果集中每一行的代码示例:

while (rows.next()) {
    // 处理当前行
}
3.2 从结果集中获取数据

可以使用 ResultSet 接口的方法从当前行检索数据,每个方法有两种版本:一种通过列名指定列,另一种通过索引编号指定列。例如:

String title = row.getString("title");
int year = row.getInt("year");
double price = row.getDouble("price");

也可以使用索引编号:

String title = row.getString(1);
int year = row.getInt(2);
double price = row.getDouble(3);

需要注意的是,列索引从 1 开始,而不是 0。

以下是一个完整的程序示例,用于从 Movies 数据库中读取数据并在控制台列出:

import java.sql.*;
import java.text.NumberFormat;

public class ListMovies {
    public static void main(String[] args) {
        NumberFormat cf = NumberFormat.getCurrencyInstance();
        ResultSet movies = getMovies();
        try {
            while (movies.next()) {
                Movie m = getMovie(movies);
                String msg = Integer.toString(m.year);
                msg += ": " + m.title;
                msg += " (" + cf.format(m.price) + ")";
                System.out.println(msg);
            }
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
    }

    private static ResultSet getMovies() {
        Connection con = getConnection();
        try {
            Statement s = con.createStatement();
            String select = "Select title, year, price " + "from movie order by year";
            ResultSet rows;
            rows = s.executeQuery(select);
            return rows;
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
        return null;
    }

    private static Connection getConnection() {
        Connection con = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            String url = "jdbc:mysql://localhost/Movies";
            String user = "root";
            String pw = "NuttMutt";
            con = DriverManager.getConnection(url, user, pw);
        } catch (ClassNotFoundException e) {
            System.out.println(e.getMessage());
            System.exit(0);
        } catch (SQLException e) {
            System.out.println(e.getMessage());
            System.exit(0);
        }
        return con;
    }

    private static Movie getMovie(ResultSet movies) {
        try {
            String title = movies.getString("Title");
            int year = movies.getInt("Year");
            double price = movies.getDouble("Price");
            return new Movie(title, year, price);
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
        return null;
    }

    private static class Movie {
        public String title;
        public int year;
        public double price;

        public Movie(String title, int year, double price) {
            this.title = title;
            this.year = year;
            this.price = price;
        }
    }
}
4. 更新 SQL 数据

除了执行 select 语句,还可以使用 Statement 对象执行 insert update delete 语句。使用 executeUpdate 方法代替 executeQuery 方法,该方法返回一个 int 值,表示更新的行数。

以下是一个向 friend 表中插入一行的方法示例:

private static void loanMovie(int id, String lastName, String firstName) {
    Connection con = getConnection();
    try {
        Statement stmt = con.createStatement();
        String insert = "insert into friend " + "(lastname, firstname, movieid) " + "values (" + "\"" + lastName + "\", \"" + firstName + "\", " + id + ")";
        int i = stmt.executeUpdate(insert);
        if (i == 1) {
            System.out.println("Loan recorded.");
        } else {
            System.out.println("Loan not recorded.");
        }
    } catch (SQLException e) {
        System.out.println(e.getMessage());
        System.exit(0);
    }
}
5. 使用可更新的行集对象

如果使用支持 JDBC 2.0 或更高版本的较新 JDBC 驱动程序,可以使用可更新的结果集来更新数据。可更新的结果集允许更改结果集中的行数据、添加行或删除行,对结果集所做的更改会自动写回到基础数据库。

要创建可更新的结果集,需要在创建 Statement 对象时指定 ResultSet.CONCUR_UPDATABLE 字段,示例代码如下:

Statement stmt = con.createStatement(
    ResultSet.TYPE_SCROLL_SENSITIVE,
    ResultSet.TYPE_CONCUR_UPDATABLE);

第一个参数表示结果集是可滚动的,即可以在结果集中前后移动游标;第二个参数表示结果集是可更新的,对结果集所做的任何更改都会自动写回到数据库。

5.1 删除行

要从结果集中删除一行,可以使用导航方法将游标移动到要删除的行,然后使用 deleteRow 方法删除该行。示例代码如下:

try {
    rs.absolute(3);
    rs.deleteRow();
} catch (SQLException e) {
    System.out.println(e.getMessage());
    System.exit(0);
}
5.2 更新行的列值

要更新行的列值,先导航到要更新的行,然后使用更新方法更改一个或多个列值,最后调用 updateRow 方法应用更改。示例代码如下:

try {
    rs.absolute(6);
    rs.updateInt("year", 1975);
    rs.updateRow();
} catch (SQLException e) {
    System.out.println(e.getMessage());
    System.exit(0);
}
5.3 插入行

插入行时,使用结果集中的一个特殊行“插入行”。具体步骤如下:
1. 调用 moveToInsertRow 方法将游标移动到插入行。
2. 使用更新方法为插入行的每一列设置值。
3. 调用 insertRow 方法将插入行复制到结果集,从而在数据库中写入新行。
4. 调用 moveToCurrentRow 方法返回到结果集中的上一个位置。

以下是插入行的示例代码:

try {
    rs.moveToInsertRow();
    rs.updateString("title", "Monty Python and the Holy Grail");
    rs.updateInt("year", 1975);
    rs.updateDouble("price", 13.95);
    rs.insertRow();
    rs.moveToCurrentRow();
} catch (SQLException e) {
    System.out.println(e.getMessage());
    System.exit(0);
}

通过以上步骤,你可以使用 JDBC 连接到数据库、执行查询和更新操作,实现 Java 程序与数据库的交互。希望这些内容对你有所帮助!

使用 JDBC 连接数据库:全面指南

6. 总结与注意事项

在使用 JDBC 进行数据库操作时,有几个关键要点需要牢记,以下是对整个流程的总结以及一些重要的注意事项:

6.1 流程总结
  • 设置驱动程序 :可选择 ODBC 或数据库连接器。ODBC 通用但效率低,适合小型应用和测试;数据库连接器专为特定数据库设计,更高效强大。
  • 连接数据库 :先注册驱动程序类,再使用 DriverManager.getConnection 方法打开连接。
  • 查询数据库 :使用 Connection Statement ResultSet 类和接口执行 select 语句,遍历结果集并获取数据。
  • 更新数据 :使用 Statement 对象的 executeUpdate 方法执行 insert update delete 语句。
  • 可更新行集对象 :使用支持 JDBC 2.0 或更高版本的驱动程序时,可创建可更新的结果集进行数据更新。
6.2 注意事项
  • 异常处理 :在注册驱动程序和打开连接时,需要捕获 ClassNotFoundException SQLException 异常,确保程序的健壮性。
  • 资源管理 :使用完 Connection Statement ResultSet 对象后,应及时关闭,避免资源泄漏。可使用 try-with-resources 语句简化资源管理。
  • SQL 注入 :在拼接 SQL 语句时,要注意防止 SQL 注入攻击。可使用预编译语句 PreparedStatement 来避免此类问题。
7. 示例流程图

下面是一个使用 mermaid 语法绘制的 JDBC 操作数据库的流程图,展示了从设置驱动到更新数据的整个过程:

graph LR
    classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px;
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
    classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px;

    A([开始]):::startend --> B(设置驱动程序):::process
    B --> C{选择驱动类型}:::decision
    C -->|ODBC| D(设置 ODBC 数据源):::process
    C -->|数据库连接器| E(设置 MySQL JDBC 连接器):::process
    D --> F(连接数据库):::process
    E --> F
    F --> G(执行查询或更新操作):::process
    G --> H{操作类型}:::decision
    H -->|查询| I(执行 select 语句):::process
    H -->|更新| J(执行 insert/update/delete 语句):::process
    I --> K(处理结果集):::process
    J --> L(检查更新行数):::process
    K --> M([结束]):::startend
    L --> M
8. 常见问题解答

在使用 JDBC 过程中,可能会遇到一些常见问题,以下是一些解答:

8.1 驱动程序找不到

如果在注册驱动程序时抛出 ClassNotFoundException 异常,可能是以下原因:
- 驱动程序 .jar 文件未正确添加到 ClassPath 变量中。
- 驱动程序类名拼写错误。

解决方法:检查 ClassPath 变量是否包含驱动程序的 .jar 文件路径,确保驱动程序类名正确。

8.2 连接数据库失败

如果在打开连接时抛出 SQLException 异常,可能是以下原因:
- 数据库 URL、用户名或密码错误。
- 数据库服务器未启动。
- 网络连接问题。

解决方法:检查数据库 URL、用户名和密码是否正确,确保数据库服务器已启动,检查网络连接是否正常。

8.3 结果集操作异常

在遍历结果集或获取数据时,如果抛出 SQLException 异常,可能是以下原因:
- 结果集已关闭。
- 游标位置超出结果集范围。

解决方法:确保结果集未关闭,在使用游标移动方法时,检查返回值以确保游标位置合法。

9. 总结

通过本文的介绍,你已经了解了如何使用 JDBC 连接到数据库、执行查询和更新操作。从设置驱动程序到使用可更新的行集对象,每个步骤都有详细的说明和示例代码。同时,我们还总结了流程、注意事项,提供了流程图和常见问题解答,希望能帮助你更好地掌握 JDBC 编程。

在实际应用中,建议根据具体需求选择合适的驱动程序和操作方法,注意异常处理和资源管理,以确保程序的稳定性和性能。不断实践和探索,你将能够熟练运用 JDBC 实现各种复杂的数据库操作。

如果你在使用 JDBC 过程中遇到任何问题,欢迎在评论区留言,我们将尽力为你解答。祝你编程愉快!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值