1. JDBC概述
1.1. JDBC介绍
JDBC的全称是Java数据库连接(Java Database Connectivity),它是一套用于执行SQL语句的Java API。应用程序可通过这套Java API连接到关系数据库,并使用SQL语句完成对数据库中数据的查询、新增、更新和删除等操作。使用JDBC连接数据库驱动,用户就不必用户不必编写Java程序与数据库交互的底层代码,使得代码的通用性更强。
1.2. JDBC访问数据库的方式
由上图可知,不同的数据库需要使用不同的JDBC驱动进行连接,例如,访问MySQL数据库需要使用MySQL驱动,访问Oracle数据库需要使用Oracle驱动。而JDBC在应用程序与数据库之间起到了一个桥梁作用。应用程序与数据库连接成功后即可对数据库进行相应的操作。
1.3. JDBC驱动程序
本地协议驱动是用使用纯Java语言编写的。本地协议驱动通常由数据库厂商直接提供驱动的JAR包,本地协议驱动程序直接将JDBC调用转换为数据库特定的网络通信协议,然后与数据库进行交互。本章将基于Native Protocol Driver类型对JDBC进行讲解,通过本地协议驱动操作数据库的方式:
2. JDBC的常用API
JDBC的核心就是为开发人员提供操作数据库的Java API类库,Java程序开发人员可以利用这些类库开发数据库应用程序,如创建数据库连接、执行SQL语句、检索结果集、访问数据库元数据等。JDBC的 API主要位于java.sql包中,该包定义了一系列访问数据库的接口和类。本节将针对java.sql包内常用的接口和类进行详细讲解。
2.1. Driver接口
Driver接口是所有JDBC驱动程序必须实现的接口,该接口专门提供给数据库厂商使用。需要注意的是,在编写JDBC程序时,必须要把所使用的数据库驱动程序(这里指MySQL驱动JAR包)或类库加载到项目的classpath中。
2.2. DriverManager类
使用JDBC连接数据库,需要用到DriverManager类,DriverManager类用于加载JDBC驱动并且创建JDBC程序与数据库的连接。在DriverManager类中,定义了两个比较重要的静态方法,如下所示。
方法声明 | 功能描述 |
registerDriver(Driver driver) | 该方法用于向DriverManager中注册给定的JDBC驱动程序 |
getConnection(String url,String user,String password) | 该方法用于建立和数据库的连接,并返回表示连接的Connection对象 |
2.3. Connection接口
DriverManager类的getConnection()方法返回了一个Connection对象,Connection对象是表示数据库连接的对象,只有获得该连接对象,才能访问并操作数据库。一个应用程序可与单个数据库建立一个或多个连接,也可以与多个数据库建立连接。Connection接口的常用方法如下所示。
方法声明 | 功能描述 |
createStatement() | 用于创建一个Statement对象,Statement对象可以将SQL语句发送到数据库 |
prepareStatement(String sql) | 用于创建一个PreparedStatement对象,该对象可以将参数化的动态SQL语句发送到数据库 |
prepareCall(String sql) | 用于创建一个CallableStatement对象来调用数据库的存储过程 |
isReadOnly() | 用于查看当前Connection对象的读取模式是否为只读模式 |
setReadOnly() | 用于设置当前Connection对象的读写模式,默认是非只读模式 |
commit() | 使所有上一次提交/回滚后进行的更改成为持久更改,并释放此Connection对象当前持有的所有数据库锁 |
setAutoCommit(boolean autoCommit) | 设置是否关闭自动提交模式 |
roolback() | 用于取消在当前事务中进行的所有更改,并释放此Connection对象当前持有的所有数据库锁 |
close() | 用于立即释放Connection对象的数据库和JDBC资源,而不是等它们被自动释放 |
isClose() | 用于判断Connection对象是否已被自动关闭 |
2.4. Statement接口
Statement接口用于执行静态的SQL语句,并返回一个结果对象。Statement接口对象可以通过Connection实例的createStatement()方法获得,该对象会把静态的SQL语句发送到数据库中编译执行,然后返回数据库的处理结果。Statement接口提供了3个常用的执行SQL语句的方法,如下所示。
方法声明 | 功能描述 |
execute(String sql) | 用于执行各种SQL语句。该方法返回一个boolean类型的值,如果返回值为true,表示所执行的SQL语句有查询结果,可以通过Statement的getResultSet()方法获得查询结果。 |
executeUpdate(String sql) | 用于执行SQL中的insert、update和delete语句。该方法返回一个int类型的值,表示数据库中受该SQL语句影响的条数。 |
executeQuery(String sql) | 用于执行SQL中的select语句。该方法返回一个表示查询结果的ResultSet对象。 |
2.5. PreparedStatement 接口
PreparedStatement是Statement的子接口,用于执行预编译的SQL语句。PreparedStatement接口扩展了带有参数SQL语句的执行操作,该接口中的SQL语句可以使用占位符?代替参数,然后通过setter方法为SQL语句的参数赋值。PreparedStatement接口提供的常用方法,如下所示。
方法声明 | 功能描述 |
executeUpdate() | 在PreparedStatement对象中执行 SQL 语句,SQL语句必须是一个DML语句或者是无返回内容的SQL语句,如DDL语句。 |
executeQuery() | 在PreparedStatement对象中执行SQL查询,该方法返回的是ResultSet对象。 |
setInt(int parameterIndex, int x) | 将指定参数设置成给定的int值。 |
setFloat(int index,float f) | 将指定位置的参数设置为float值。 |
setLong(int index,long l) | 将指定位置的参数设置为long值。 |
setDouble(int index,double d) | 将指定位置的参数设置为double值。 |
setBoolean(int index,boolean b) | 将指定位置的参数设置为boolean值。 |
void setString(int parameterIndex,String x) | 将指定参数设置成给定的String值。 |
在上表中,DML(数据操纵语言)语句指的是操作数据库、表、列等的语句,使用的关键字为CREATE、 ALTER、 DROP。DDL(数据定义语言)语句指的是对表中的数据进行增、删、改操作的语句,使用的关键字为INSERT 、UPDATE、 DELETE。
2.6. ResultSet接口
ResultSet接口用于保存JDBC执行查询时返回的结果集,该结果集封装在一个逻辑表格中。在ResultSet接口内部有一个指向表格数据行的游标(或指针),ResultSet对象初始化时,游标在表格的第一行之前,调用next()方法可以将游标移动到下一行。如果下一行没有数据,则next()方法返回false。在应用程序中经常使用next()方法作为while循环的条件来迭代ResultSet结果集。ResultSet接口的常用方法,如下所示。
方法声明 | 功能描述 |
getString(int columnIndex) | 用于获取指定字段的String类型的值,参数columnIndex代表字段的索引 |
getString(String columnName) | 用于获取指定字段的String类型的值,参数columnName代表字段的名称 |
getInt(int columnIndex) | 用于获取指定字段的int类型的值,参数columnIndex代表字段的索引 |
getInt(String columnName) | 用于获取指定字段的int类型的值,参数columnName代表字段的名称 |
absolute(int row) | 将游标移动到结果集的第row条记录 |
relative(int row) | 按相对行数(正或负)移动游标 |
previous() | 将游标从结果集的当前位置移动到上一行 |
next() | 将游标从结果集的当前位置移动到下一行 |
beforeFirst() | 将游标移动到结果集的开头(第一行之前) |
isBeforeFirst() | 判断游标是否位于结果集的开头(第一行之前) |
afterLast() | 将游标指针移动到结果集的末尾(最后一行之后) |
isAfterLast() | 判断游标是否位于结果集的末尾(最后一行之后) |
first() | 将游标移动到结果集的第一行 |
isFirst() | 判断游标是否位于结果集的第一行 |
last() | 将游标移动到结果集的最后一条记录 |
getRow() | 返回当前记录的行号 |
getStatement() | 返回生成结果集的Statement对象 |
close() | 释放当前结果集的数据库和JDBC资源 |
从表中可以看出,ResultSet接口中定义了一些getter方法,而采用哪种getter方法获取数据取决于字段的数据类型。程序既可以通过字段的名称来获取指定数据,也可以通过字段的索引来获取指定的数据,字段的索引是从1开始编号的。
3. JDBC编程
3.1. JDBC编程步骤简述
通常情况下,使用JDBC API实现JDBC程序时,首先需要加载并注册数据库驱动程序,其次使用 DriverManager类调用getConnection()方法获取表示数据连接的Connection对象,最后通过Connection对象调用相应方法获取Statement对象,通过Statement对象执行SQL语句。执行SQL语句之后,如果数据库有返回结果,则将结果封装为ResultSet对象返回。
3.2. JDBC编程流程图
使用JDBC的常用API实现JDBC程序的步骤如下所示。
3.3. JDBC编程步骤详述
(1)加载并注册数据库驱动程序
在连接数据库之前,要加载数据库的驱动到JVM(Java虚拟机)。加载数据库驱动操作可以通过java.lang.Class类的静态方法forName(String className)或DriverManager类的静态方法registerDriver(Driver driver)实现,具体示例如下所示:
DriverManager.registerDriver(Driver driver);
或
Class.forName("DriverName");
forName()方法的参数DriverName:表示数据库的驱动类。以MySQL数据库为例,MySQL驱动类在MySQL 6.0.2版本之前是com.mysql.jdbc.Driver,而在MySQL 6.0.2版本之后,MySQL驱动类是com.mysql.cj.jdbc.Driver。
(2)通过DriverManager获取数据库连接
DriverManager类的getConnection()方法用于获取JDBC驱动程序到数据库的连接,通过DriverManager类获取数据库连接的具体方式如下:
Connection conn = DriverManager.getConnection(String url, String user, String pwd);
从上述代码可以看出,getConnection()方法有3个参数,分别表示连接数据库的URL、登录数据库的用户名和登录数据库的密码。
(3)通过Connection对象获取Statement对象
获取Connetction对象之后,还必须要创建一个Statement对象,将各种SQL语句发送到所连接的数据库中执行。如果把Connection对象看作一条连接程序和数据库的索道,那么Statement对象就可以看作是索道上的一辆缆车,它为数据库传输SQL语句,并返回执行结果。
(4)使用Statement执行SQL语句
创建了Statement对象后,就可以通过该对象执行SQL语句。如果SQL语句运行后产生了结果集,Statement对象会将结果集封装成ResultSet对象并返回。Statement有以下3个执行SQL语句的方法。
execute():可以执行任何SQL语句。
executeQuery():通常执行查询语句,执行后返回代表结果集的ResultSet对象。
executeUpdate():主要用于执行DML语句和DDL语句。执行DML语句,如INSERT、UPDATE或DELETE时,返回受SQL语句影响的行数;执行DDL语句返回0。
(5)操作结果集
如果执行的SQL语句是查询语句,执行结果将返回一个ResultSet对象,该对象保存了SQL语句查询的结果。程序可以通过操作该ResultSet对象取出查询结果。
(6)关闭连接,释放资源
每次操作数据库结束后都要关闭数据库连接并释放资源,以防止系统资源浪费。资源的关闭顺序和声明顺序相反,关闭顺序依次为关闭结果集对象ResultSet、关闭Statement对象、关闭Connection对象。为了保证在异常情况下也能关闭资源,通常在try...catch语句的finally代码块中统一关闭资源。