当Java应用程序使用JDBC接口访问数据库时,整个数据访问过程大致可分为以下几个步骤。
在上述的操作过程中,开发人员需要使用如下几个核心概念。
我们将以连接PostgreSQL数据库为例,展示如何使用JDBC接口查询数据库。如果读者对其他数据库感兴趣,也可以根据我们的提示,将代码示例修改为相应的数据库应用程序。
如果使用Maven管理项目的话,需要在pom.xml中添加如下依赖关系。
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.18</version>
</dependency>
如果使用Gradle管理项目的话,需要在build.gradle中添加如下依赖关系。
repositories {
mavenCentral()
}
dependencies {
compile group: 'org.postgresql', name: 'postgresql', version: '42.2.18'
}
当开发人员使用MySQL数据库时,需将Maven和Gradle配置文件中的驱动程序改为mysql-connector-java。使用Oracle时,需改为ojdbc。
假设我们在本地数据库中有一张student的表,它的内容如下。student表中有三列数据:
Name | Age | Gender |
---|---|---|
Adam | 18 | Male |
Cindy | 19 | Female |
我们首先定义StudentBean类,用于表示学生。StudentBean中的成员变量与表中各列数据一一对应。
public class StudentBean {
private String name = null;
private Integer Age = null;
private String gender = null;
}
在StudentDB类中,我们实现了fetchAll()方法获取所有学生的信息。首先,我们在第一步中加载PostgreSQL的驱动程序。如果使用MySQL或者Oracle数据库的话,需要将MySQL和Oracle数据库的驱动程序类名传入Class.forName()方法中。
第二步是创建Connection对象,与数据库建立连接。JDBC支持多种建立数据库连接的方式,我们在例子中使用用户名和密码的方法检查用户合法性。不同数据库有着不同的url格式,因此,开发人员需要根据相应的格式构建url字符串。
在创建出Connection对象之后,开发人员就可以通过这个Connection对象向数据库发送"指令"了。但是,需要注意的是,当使用完毕之后,开发人员需要调用close()方法关闭Connection对象。因为,如果不关闭该连接的话,会造成"连接泄漏(Connection Leak)"错误。当该错误积累到一定程度时,将无法再与数据库建立新的连接。因为,在数据库看来,它已创建了足够多的连接了。
第三步是创建Statement对象用于执行查询语句。JDBC不仅支持多种方式来执行查询语句,而且还支持增加(Insert)、删除(Delete)、修改(Update)等语句。我们将在后续章节中详细介绍这些内容。在本例中,我们通过调用executeQuery()方法查询student表中的所有数据。类似的,使用完毕后,开发人员需要关闭Statement对象。所以,我们使用try-with-resource语句来帮助开发人员自动完成关闭操作。
当查询操作完成后,executeQuery()方法会返回一个ResultSet对象,用来表示查询的结果。ResultSet对象实际上维护的是类似于表结构的数据。ResultSet对象内部还保存着一个"游标"(Cursor)。初始时,这个"游标"指向第一行之前的位置(The cursor is positioned before the first row)。当开发人员调用next()方法后,这个"游标"会向前移动一行。因此,在第一次调用next()方法之后,这个"游标"会指向第一行。再调用一次next()方法后,这个"游标"会指向第二行。以此类推。在这个过程中,如果这个"游标"还能向后移动的话,换句话说,如果该"游标"尚未指向最后一行的话,next()方法会返回true,表示该"游标"还可以向前移动。如果当这个"游标"到达最后一行后,next()方法会返回false。在此之后,开发人员不应再调用next()函数移动该"游标"。
当这个"游标"指向某一行时,开发人员可以使用get*()方法来获取该行某一列的数据。当数据是字符串时,应使用getString()方法。当数据是整数时,应使用getInt()。get*()可以以列名或者列序号的方式获取该列数据。列名为字符串类型;序列号为整数类型。列序号从1开始。更多get*()方法的使用方法可参见ResultSet类的开发文档。
根据上述的ResultSet的使用方法,我们使用了while循环来遍历每一列。当"游标"指向某一行时,我们获取了该行的Name, Age和Gender数据。并根据这些数据,创建StudentBean对象,添加到allStudents列表中。
在处理完所有查询的数据之后,我们直接返回allStudents列表。注意,Connection和Statement对象会被自动关闭。她们关闭的顺序与她们创建的顺序正好相反,这是由try-with-resource特性确保的。
public class StudentDB {
public List<Student> fetchAll() {
List<Student> allStudents = new ArrayList<Student>();
try {
// 第一步:加载数据库驱动程序
Class.forName("org.postgresql.Driver");
// 当使用MySQL数据库时,需使用
// Class.forName("com.mysql.jdbc.Driver").newInstance();
// 当使用Oracle数据库时,需使用
// Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (Exception ex) {
System.err.println("org.postgresql.Driver not found.");
return null;
}
// 第二步:当使用MySQL数据库时,需使用
// String url = "jdbc:mysql://localhost/dbname";
// 当使用Oracle数据库时,需使用
// String url = "jdbc:oracle:thin@myhost:dbname";
String url = "jdbc:postgresql://localhost/dbname";
String username = "littlewaterdrop";
String password = "password";
// 创建Connection对象,并使用try-with-resource语句在使用完毕后自动关闭Connection对象。
try (Connection connection = DriverManager.getConnection(url, username, password)) {
// 第三步:创建Statement对象,并使用try-with-resource语句在使用完毕后自动关闭Statement对象。
try (Statement stmt = connection.createStatement()) {
// 执行查询语句
ResultSet result = stmt.executeQuery("select name, age, gender from student;");
// 第四步:遍历所有返回的数据,将其添加在allStudents列表中
while (result.next()) {
String name = result.getString("name");
Integer age = result.getInt("age");
String gender = result.getString("gender");
allStudents.add(new Student(name, age, gender));
}
}
}
// 第五步,返回获得的数据
return allStudents;
}
}
本章介绍了使用JDBC接口访问数据库的基本原理和流程。在该流程中,应用程序需依次加载驱动程序,建立数据库连接,创建Statement对象,执行查询语句并检查查询结果。在完成所有的操作之后,应用程序还需要关闭Statement对象和Connection对象。这些是使用JDBC接口的基本流程。我们将在后续的章节中详细的介绍数据操作的几种不同的方式。
注册用户登陆后可留言