第9章 JDBC
Java 连接数据库的标准接口:Driver、Connection、Statement、PreparedStatement、ResultSet。
本章学习目标
- 能加载驱动、建立数据库连接
- 能用 Statement 与 PreparedStatement 执行 SQL
- 能遍历 ResultSet 取出查询结果
- 知道用 PreparedStatement 防止 SQL 注入
本章导览
核心内容
什么是JDBC
定义:JDBC(Java Database Connectivity,Java数据库连接),它是一套用于执行SQL语句的Java API。
作用:应用程序可通过这套API连接到关系型数据库,并使用SQL语句来完成对数据库中数据的查询、新增、更新和删除等操作。
说明:
不同的数据库(如MySQL、Oracle等)在其内部处理数据的方式是不同的,因此每一个数据库厂商都提供了自己数据库的访问接口。
直接使用数据库厂商提供的访问接口操作数据库,程序的可移植性变得很差。
而JDBC要求各个数据库厂商按照统一的规范来提供数据库驱动,由JDBC和具体的数据库驱动联系,这样应用程序就不必直接与底层的数据库交互,从而使得代码的通用性更强。
应用程序使用JDBC访问数据库的方式:
说明:JDBC在应用程序与数据库之间起到了一个桥梁作用,当应用程序使用JDBC访问特定的数据库时,只需要通过不同的数据库驱动与其对应的数据库进行连接,连接后即可对该数据库进行相应的操作。

📄 展开课件原文(第 6–8 页,共 3 页)
JDBC常用API
定义:Driver接口是所有JDBC驱动程序必须实现的接口,该接口专门提供给数据库厂商使用。
注意:在编写JDBC程序时,必须要把所使用的数据库驱动程序或类库加载到项目的classpath中(这里指数据库的驱动JAR包)。
定义:DriverManager类用于加载JDBC驱动并且创建与数据库的连接。
主要方法:
注意:在实际开发中,通常不使用registerDriver(Driver driver) 注册驱动。因为JDBC驱动类Driver中有一段静态代码块,是向DriverManager注册一个Driver实例,当再次执行registerDriver(new Driver()),相当于实例化了两个Driver对象,因此在加载数据库驱动时通常使用Class类的静态方法forName()来实现。| 方法声明 | 功能描述 |
|---|---|
| static synchronized void registerDriver(Driver driver) | 该方法用于向DriverManager中注册给定的JDBC驱动程序 |
| static Connection getConnection(String url,String user,String pwd) | 该方法用于建立和数据库的连接,并返回表示连接的Connection对象 |
定义:Connection接口代表Java程序和数据库的连接对象,只有获得该连接对象后,才能访问数据库,并操作数据表。
常用方法:
| 方法声明 | 功能描述 |
|---|---|
| Statement createStatement() | 该方法用于返回一个向数据库发送语句的Statement对象 |
| PreparedStatement prepareStatement(String sql) | 该方法用于返回一个PreparedStatement对象,该对象用于向数据库发送参数化的SQL语句 |
| CallableStatement prepareCall(String sql) | 该方法用于返回一个CallableStatement对象,该对象用于调用数据库中的存储过程 |
定义:Statement是Java执行数据库操作的一个重要接口,它用于执行静态的SQL语句,并返回一个结果对象。
说明:Statement接口对象可以通过Connection实例的createStatement()方法获得,然后返回数据库的处理结果。
| 方法声明 | 功能描述 |
|---|---|
| boolean execute(String sql) | 用于执行各种SQL语句,返回一个boolean类型的值,如果为true,表示所执行的SQL语句有查询结果,可通过Statement的getResultSet()方法获得查询结果 |
| int executeUpdate(String sql) | 用于执行SQL中的insert、update和delete语句。该方法返回一个int类型的值,表示数据库中受该SQL语句影响的记录条数 |
| ResultSet executeQuery(String sql) | 用于执行SQL中的select语句,该方法返回一个表示查询结果的ResultSet对象 |
Statement接口封装了JDBC执行SQL语句的方法,虽然可以完成Java程序执行SQL语句的操作,但是在实际开发过程中往往需要将程序中的变量作为SQL语句的查询条件,而使用Statement接口操作这些SQL语句会过于繁琐,并且存在安全方面的问题。
针对这一问题,JDBC API 中提供了扩展的PreparedStatement接口。
PreparedStatement有什么作用?
定义:PreparedStatement是Statement的子接口,用于执行预编译的SQL语句。
说明:PreparedStatement接口扩展了带有参数SQL语句的执行操作,应用接口中的SQL语句可以使用占位符“?”来代替其参数,然后通过setXxx()方法为SQL语句的参数赋值。
| 方法声明 | 功能描述 |
|---|---|
| int executeUpdate() | 在此PreparedStatement对象中执行 SQL 语句,该语句必须是一个DML语句或者是无返回内容的SQL 语句,如 DDL 语句 |
| ResultSet executeQuery() | 在此PreparedStatement对象中执行 SQL 查询,该方法返回的是ResultSet对象 |
| void setInt(int parameterIndex, int x) | 将指定参数设置为给定的int值 |
| void setFloat(int parameterIndex, float x) | 将指定参数设置为给定的float值 |
| void setString(int parameterIndex, String x) | 将指定参数设置为给定的String值 |
| void setDate(int parameterIndex, Date x) | 将指定参数设置为给定的Date值 |
| void addBatch() | 将一组参数添加到此PreparedStatement对象的批处理命令中 |
| void setCharacterStream(int parameterIndex, java.io.Reader reader, int length) | 将指定的输入流写入数据库的文本字段 |
| void setBinaryStream(int parameterIndex, java.io.InputStream x, int length) | 将二进制的输入流数据写入到二进制字段中 |
使用:为SQL语句参数赋值时,可以通过输入参数与SQL类型相匹配的setXxx()方法。例如字段的数据类型为int或Integer,那么应该使用setInt()方法,也可以通过setObject()方法设置多种类型的输入参数。
示例:
// 假设users表中字段id、name、email类型分别是int、varchar、varchar
String sql = "INSERT INTO users(id,name,email) VALUES(?,?,?)";
PreparedStatement preStmt = conn.prepareStatement(sql);
preStmt.setInt(1, 1); //使用参数与SQL类型相匹配的方法
preStmt.setString(2, "zhangsan"); //使用参数与SQL类型相匹配的方法
preStmt.setObject(3, "zs@sina.com"); //使用setObject()方法设置参数
preStmt.executeUpdate();定义:ResultSet接口用于保存JDBC执行查询时返回的结果集,该结果集封装在一个逻辑表格中。
说明:
在ResultSet接口内部有一个指向表格数据行的游标(或指针),ResultSet对象初始化时,游标在表格的第一行之前,调用next()方法可将游标移动到下一行。如果下一行没有数据,则返回false。
在程序中经常使用next()方法作为while循环的条件来迭代ResultSet结果集。
| 方法声明 | 功能描述 |
|---|---|
| String getString(int columnIndex) | 用于获取指定字段的String类型的值,参数columnIndex代表字段的索引 |
| String getString(String columnName) | 用于获取指定字段的String类型的值,参数columnName代表字段的名称 |
| int getInt(int columnIndex) | 用于获取指定字段的int类型的值,参数columnIndex代表字段的索引 |
| int getInt(String columnName) | 用于获取指定字段的int类型的值,参数columnName代表字段的名称 |
| Date getDate(int columnIndex) | 用于获取指定字段的Date类型的值,参数columnIndex代表字段的索引 |
| Date getDate(String columnName) | 用于获取指定字段的Date类型的值,参数columnName代表字段的名称 |
| boolean next() | 将游标从当前位置向下移一行 |
| boolean absolute(int row) | 将游标移动到此 ResultSet 对象的指定行 |
| void afterLast() | 将游标移动到此 ResultSet 对象的末尾,即最后一行之后 |
| void beforeFirst() | 将游标移动到此 ResultSet 对象的开头,即第一行之前 |
| boolean previous() | 将游标移动到此 ResultSet 对象的上一行 |
| boolean last() | 将游标移动到此 ResultSet 对象的最后一行 |
ResultSet接口中定义了大量的getXxx()方法,而采用哪种getXxx()方法取决于字段的数据类型。
程序既可以通过字段的名称来获取指定数据,也可以通过字段的索引来获取指定的数据,字段的索引是从1开始编号的。
例如,假设数据表的第1列字段名为id,字段类型为int,那么既可以使用getInt("id")获取该列的值,也可以使用getInt(1)获取该列的值。
📄 展开课件原文(第 9–19 页,共 11 页)
JDBC编程
1
加载数据库驱动
2
通过DriverManager获取数据库驱动
3
通过Connection对象获取Statement对象
4
使用Statement执行SQL语句
5
操作ResultSet结果集
6
关闭连接,释放资源
语法:
示例:
加载MySQL数据库驱动
加载Oracle数据库的驱动
Class.forName("DriverName");
Class.forName("com.mysql.jdbc.Driver");
Class.forName("oracle.jdbc.driver.OracleDriver");DriverName就是数据库驱动类所对应的字符串
url语法(以MySQL数据库为例):
通过DriverManager获取数据库连接
Connection conn = DriverManager.getConnection(String url,
String user, String pwd);jdbc:mysql://hostname:port/databasename
登录数据库的用户名和密码
连接数据库的URL
jdbc:mysql:是固定的写法,mysql指的是MySQL数据库
hostname指主机的名称
databasename指的是MySQL中相应数据库的名称
port指的是连接数据库的端口号(MySQL端口号默认为3306)
创建方式:
createStatement():创建基本的Statement对象。
prepareStatement(String sql):根据传递的SQL语句创建PreparedStatement对象。
prepareCall(String sql):根据传入的SQL语句创建CallableStatement对象。
示例(以创建基本的Statement对象为例):
Statement stmt = conn.createStatement();执行SQL方式:
execute(String sql):用于执行任意的SQL语句。
executeQuery(String sql):用于执行查询语句,返回ResultSet结果集对象。
executeUpdate(String sql):主要用于执行DML(数据操作语言)和DDL(数据定义语言)语句。执行DML语句(INSERT、UPDATE或DELETE)时,会返回受SQL语句影响的行数,执行DDL(CREATE、ALTER)语句返回0。
示例(以executeQuery()方法为例):
// 执行SQL语句,获取结果集ResultSet
ResultSet rs = stmt.executeQuery(sql);说明:
如果执行的SQL语句是查询语句,执行结果将返回一个ResultSet对象,该对象里保存了SQL语句查询的结果。
程序可以通过操作该ResultSet对象来取出查询结果。
说明:每次操作数据库结束后都要关闭数据库连接,释放资源,以重复利用资源
注意:
通常资源的关闭顺序与打开顺序相反,顺序是ResultSet、Statement(或PreparedStatement)和Connection。
为了保证在异常情况下也能关闭资源,需要在try...catch的finally代码块中统一关闭资源。
1、搭建数据库环境
2、创建项目环境,导入数据库驱动
3、编写JDBC程序器
案例代码
接下来通过一个案例来演示JDBC的具体使用。该程序从tb_user表中读取数据,并将结果打印在控制台。请查看教材9.3.2小节的案例代码。
📄 展开课件原文(第 20–27 页,共 8 页)
案例——使用JDBC实现QQ登录
任务案例
案例代码
接下来,通过一个使用JDBC实现QQ登录的案例来熟悉JDBC编程的使用。请查看教材9.4小节。
📄 展开课件原文(第 28–28 页,共 1 页)
本章小结
本章主要讲解了JDBC的基本知识,包括什么是JDBC、JDBC的常用API、如何使用JDBC进行编程,以及如何在项目中使用JDBC。通过本章的学习,读者不仅可以了解到什么是JDBC,还能掌握JDBC操作数据库的步骤,以及学会如何将GUI项目与JDBC相结合进行程序开发。
📄 展开课件原文(第 29–30 页,共 2 页)
课件里的提醒 课件原文中的“注意 / 说明 / 定义”
- 定义:JDBC(Java Database Connectivity,Java数据库连接),它是一套用于执行SQL语句的Java API。
- 说明:JDBC在应用程序与数据库之间起到了一个桥梁作用,当应用程序使用JDBC访问特定的数据库时,只需要通过不同的数据库驱动与其对应的数据库进行连接,连接后即可对该数据库进行相应的操作。
- 定义:Driver接口是所有JDBC驱动程序必须实现的接口,该接口专门提供给数据库厂商使用。
- 注意:在编写JDBC程序时,必须要把所使用的数据库驱动程序或类库加载到项目的classpath中(这里指数据库的驱动JAR包)。
- 定义:DriverManager类用于加载JDBC驱动并且创建与数据库的连接。
- 注意:在实际开发中,通常不使用registerDriver(Driver driver) 注册驱动。因为JDBC驱动类Driver中有一段静态代码块,是向DriverManager注册一个Driver实例,当再次执行registerDriver(new Driver()),相当于实例化了两个Driver对象,因此在加载数据库驱动时通常使用Class类的静态方法forName()来实现。
- 定义:Connection接口代表Java程序和数据库的连接对象,只有获得该连接对象后,才能访问数据库,并操作数据表。
- 定义:Statement是Java执行数据库操作的一个重要接口,它用于执行静态的SQL语句,并返回一个结果对象。
- 说明:Statement接口对象可以通过Connection实例的createStatement()方法获得,然后返回数据库的处理结果。
- 定义:PreparedStatement是Statement的子接口,用于执行预编译的SQL语句。
- 说明:PreparedStatement接口扩展了带有参数SQL语句的执行操作,应用接口中的SQL语句可以使用占位符“?”来代替其参数,然后通过setXxx()方法为SQL语句的参数赋值。
- 定义:ResultSet接口用于保存JDBC执行查询时返回的结果集,该结果集封装在一个逻辑表格中。
本章代码速览 把课件里的示例代码集中起来,可直接复制运行
注意:在实际开发中,通常不使用registerDriver(Driver driver) 注册驱动。因为JDBC驱动类Driver中有一段静态代码块,是向DriverManager注册一个Driver实例,当再次执行registerDriver(new Driver()),相当于实例化了两个Driver对象,因此在加载数据库驱动时通常使用Class类的静态方法forName()来实现。// 假设users表中字段id、name、email类型分别是int、varchar、varcharString sql = "INSERT INTO users(id,name,email) VALUES(?,?,?)";PreparedStatement preStmt = conn.prepareStatement(sql);preStmt.setInt(1, 1); //使用参数与SQL类型相匹配的方法preStmt.setString(2, "zhangsan"); //使用参数与SQL类型相匹配的方法preStmt.setObject(3, "zs@sina.com"); //使用setObject()方法设置参数preStmt.executeUpdate();Class.forName("DriverName");Class.forName("com.mysql.jdbc.Driver");Class.forName("oracle.jdbc.driver.OracleDriver");String user, String pwd);