本关任务:通过 JDBC 的方式查询 MySQL 表 t_user 中的数据。
为了完成本关任务,你需要掌握:
JDBC(Java DataBase Connectivity)是一种用于执行 SQL 语句的 Java API,它由一组用 Java 语言编写的类和接口组成。换句话说:就是可以直接通过 Java 语言,去操作数据库。
JDBC API 提供以下接口和类:
DriverManager:此类管理数据库驱动程序列表。可在 JDBC 下识别某个子协议的第一个驱动程序,用于建立数据库连接;
方法名称 | 功能描述 |
getConnection(String url,String user,String password) | 指定 3 个入口参数(依次为连接数据库的 url、用户名和密码)来获取与数据库的连接 |
setLoginTimeout() | 获取驱动程序试图登陆到某一数据库时可以等待的最长时间,以秒为单位 |
Connection:此接口具有用于联系数据库的所有方法。 Connection 对象表示通信上下文,即与数据库的所有通信仅通过连接对象;
方法名称 | 功能描述 |
getMetaData() | 该方法用于返回数据库的元数据的 DatabaseMetaData 对象 |
createStatement | 用于创建一个 Statement 对象来将 SQL 语句发送到数据库 |
preparedStatement(String sql) | 用于创建一个 PreparedStatement 对象来将参数化的 SQL 语句发送到数据库 |
commit() | 使所有上一次提交/回滚后进行的更改成为持久更改 |
close() | 立即释放此 Connection 对象的数据库和 JDBC 资源,而不是等待它们被释放 |
Statement:用于执行静态 SQL 语句并返回它所生成结果的对象;
方法名称 | 功能描述 |
boolean execute(String sql) | 用于执行各种 SQL 语句,该方法返回一个 boolean 类型的值。如果为 true,表示所执行的 SQL 语句具备查询结果,可通过 Statement 的 getResultSet() 方法查询结果 |
int executeUpdate(String sql) | 用于执行 SQL 中的 insert、update 和 delete 语句,该方法返回一个 int 类型的值,表示影响数据库中的行数 |
ResultSet executeQuery(String sql) | 用于执行 SQL 中的 select 语句(查询,遍历),该方法返回一个表示查询结果的 ResultSet 对象 |
PrepareStatement:动态地执行 SQL,其将被预编译并保存到 PrepareStatement 实例中,从而可以反复地执行该 SQL 语句;
方法名称 | 功能描述 |
executeUpdate() | 在此 PreparedStatement 对象中执行 SQL 语句,该语句必须是一个 DML 语句,或者无返回内容的 SQL 语句,比如 DDL 语句 |
executeQuery() | 在此 PreparedStatement 对象中执行 SQL 语句,该方法返回的是 ResultSet 对象 |
setInt(int parameterIndex, int x) | 将指定的参数设置为 int 值 |
setFloat(int parameterIndex, float x) | 将指定的参数设置为 Float 值 |
setString(int parameterIndex, String x) | 将指定参数设置的给定的 Date 值 |
setDate(int parameterIndex, Date x) | 将指定参数设置给定的 Date 值 |
addBatch() | 将一组参数添加到此 PreparedStatement 对象的批处理命令中 |
ResultSet:提供检索不同类型字段的方法。(操作对象为 Statement 执行 SQL 查询后的结果);
getString(int columnIndex) | 用于获取 指定字段的 String 类型的值,参数 columnIndex 代表字段的索引 |
getString(String columnName) | ?用于获取指定字段的 String 类型的值,参数 columnIndex 代表字段名称 |
getInt(int columnIndex) | ?用于获取指定字段的 int 类型的值,参数 columnIndex 代表字段的索引 |
getInt(String columnName) | ?用于获取指定字段的 int 类型的值,参数 columnIndex 代表字段名称 |
getDate(int columnIndex) | ?用于获取指定字段的 Date类型的值,参数 columnIndex 代表字段索引 |
getDate(String columnName) | ?用于获取指定字段的 Date类型的值,参数 columnIndex 代表字段名称 |
next() | ?将游标从当前位置移到下一位置 |
SQLException:此类处理数据库应用程序中发生的任何错误。
使用 JDBC 的步骤如下:
加载数据库驱动 → 建立数据库连接(Connection) → 创建执行 SQL 语句的 Statement 对象 → 处理执行结果(ResultSet) → 释放资源。
驱动加载是为了打开与数据库的通信通道。
在注册驱动前我们需要装载特定厂商的数据库驱动程序,导入 mysq-connector-java 的 jar 包,方法是在项目中建立 lib 目录,在其下放入 jar 包(平台已准备好 jar 包,无需自己放入)。
将 jar 包导入项目之后我们就开始注册驱动:
Java 加载数据库驱动通常是使用 Class 类的静态方法 forName(),语法格式如下:
Class.forName(String driverManager)
示例:
// 需要抛出异常
try {
// 获取连接驱动
Class.forName("com.mysql.jdbc.Driver" );
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
如果加载成功,会将加载的驱动类注册给 DriverManager;加载失败,会抛出 ClassNotFoundException 异常。
成功加载完数据库驱动后,就可以建立数据库的连接了,使用 DriverManager 的静态方法 getConnection() 来实现。如下:
// 连接数据库,参数:连接的 url、用户名、密码
Connection conn = DriverManager.getConnection(url, user, password);
注意:需要抛出 SQLException 的异常。
URL 用于标识数据库的位置,通过 URL 地址告诉 JDBC 程序连接信息。
若不存在数据库,只建立连接,URL 的写法为:
若存在数据库 test,URL 的写法为:
其中 localhost 可以换成 IP 地址 127.0.0.1 ,3306 为 MySQL 数据库的默认端口号,user 和 password 对应数据库的用户名和密码。
连接建立完毕后,创建(获取)数据库操作对象,用于执行编写的 SQL 语句。
Statement createStatement() :主要用来执行 SQL 语句,但是有 SQL 注入的漏洞
PreparedStatement preparedStatement(String sql) :主要用来预编译 SQL 语句,并且执行。解决了 SQL 注入的漏洞
CallableStatement prepareCall(String sql) :主要用来执行 SQL 中的存储过程
例子:
// 编写 SQL 语句
String sql = "SELECT * FROM myuser";
// 动态执行该 SQL 语句
PreparedStatement preparedStatement = connection.prepareStatement(sql);
// 获取查询结果
ResultSet resultSet = preparedStatement.executeQuery();
// 遍历输出该结果
while (resultSet.next()){
System.out.println(resultSet.getString("name")); // 注意:这里的 name 必须与数据库的字段名称一致
}
JDBC 程序运行完后,切记要释放程序在运行过程中创建的那些与数据库进行交互的对象,这些对象通常是 ResultSet,Statement 和 Connection 对象。
特别是 Connection 对象,它是非常稀有的资源,用完后必须马上释放,如果 Connection 不能及时、正确的关闭,极易导致系统宕机。
Connection 的使用原则是尽量晚创建,尽量早的释放。
为确保资源释放代码能运行,资源释放代码一定要放在 finally 语句中。
finally {
try {
if(resultSet != null){
resultSet.close();
}
if(preparedStatement != null){
preparedStatement.close();
}
if(connection != null){
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
MySQL 的 mydb 数据库;
用户表 t_user;
列名 | 类型 | 非空 | 注释 |
---|---|---|---|
userId | int | √ | 用户 ID 主键 |
userName | varchar | √ | 用户名 |
passWord | varchar | √ | 用户密码 |
MySQL 连接配置:
Driver:com.mysql.jdbc.Driver;
URL:jdbc:mysql://localhost:3306/mydb?characterEncoding=UTF-8;
user:root;
password:123123。
仔细阅读右侧编辑区内给出的代码框架及注释,在 Begin-End 中通过 JDBC 的方式查询 MySQL 表 t_user 中的数据,输出查询结果时,用 \t 将查询字段结果分隔,格式:“userId userName passWord”,其中这些都分别对应着查询结果的值。
平台将使用测试集运行你编写的程序代码,若全部的运行结果正确,则通关。 可在右侧“测试结果”区查看具体的测试集详情。
测试输入:无
预期输出:
1 sunfeng 147258
2 dv 123456
3 suning 845966
import java.sql.*;
public class JDBCInsert {
public static void main(String[] args) throws java.io.IOException{
// 请在下面的Begin-End之间按照注释中给出的提示编写正确的代码
/********** Begin **********/
Connection conn = null;
ResultSet resultSet = null;
PreparedStatement preparedStatement = null;
// 获取数据库连接驱动
String driver = "com.mysql.jdbc.Driver";
String DB_URL = "jdbc:mysql://localhost:3306/mydb?characterEncoding=UTF-8";
// 数据库的用户名与密码,需要根据自己的设置
String USER = "root";
String PASS = "123123";
// 需要抛出异常
try {
// 获取连接驱动
Class.forName(driver);
conn = DriverManager.getConnection(DB_URL, USER, PASS);
// 编写查询 SQL
String sql = "SELECT * FROM t_user";
// 动态执行该 SQL 语句
preparedStatement = conn.prepareStatement(sql);
// 获取查询结果
resultSet = preparedStatement.executeQuery();
// 遍历输出该结果
int i = 0;
while (resultSet.next()){
i++;
System.out.println( i + "\t" + resultSet.getString("username") + "\t" +
resultSet.getString("password")); // 注意:这里的 name 必须与数据库的字段名称一致
}
} catch (Exception e) {
e.printStackTrace();
}
finally {
try {
// 关闭资源
if(resultSet != null){
resultSet.close();
}
if(preparedStatement != null){
preparedStatement.close();
}
if(conn != null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/********** End **********/
}
}