目录
JDBC 是什么
JDBC 的工作原理
JDBC 的使用
引入驱动
使用
常用接口和类
Connection
Statement
ResultSet
使用总结
JDBC 是什么
JDBC(Java Database Connectivity):Java数据库连接,是一种用于执行 SQL 语句的Java API,是 Java 数据库连接规范,为 Java 开发人员操作数据库提供了一个标准的 API,可以为多种关系数据库提供统一访问
数据库是一个类别,其中包括 MySQL、Oracle、sql server 等,这些数据库提供的 API 有所不同,也就增加了我们的学习成本
而 JDBC 为实现数据库操作提供了一套标准接口,让 Java 应用程序能够与各种数据库系统交互,而不需要关键具体数据库的实现细节
JDBC 的工作原理
JDBC 为多种关系数据库提供了统一访问方式,主要包含一些通用的接口类
JDBC 访问数据库的层次结构:
JDBC的优势:
Java语言操作数据库时完全面向抽象接口编程
开发数据库应用不用限定特定数据库厂商的API
程序的可移植性大大增强
JDBC 的使用
引入驱动
在使用 JDBC 之前,需要引入 JDBC 驱动包
在仓库中进行下载:
Maven Repository: Search/Browse/Explore (mvnrepository.com)
搜索mysql:
其中:
Connector/J 中存放的是更高版本的驱动包
Connector Java 中存放的是低版本的驱动包
根据服务器的版本选择对应驱动包:
选择对应版本的驱动包,并下载:
接着,我们将 jar 包引入到项目中
我们先创建一个新项目,并创建一个目录,并将 jar 包拷贝到这个目录中:
再右键这个新目录,add as library:
接下来,我们就可以编写代码了
使用
首先,需要创建数据源(数据源描述了需要操作的数据库在哪里),设置数据库连接的 url、用户名 和 密码:
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource) dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false");
((MysqlDataSource) dataSource).setUser("root");
((MysqlDataSource) dataSource).setPassword("123456");
其中,MySQL 数据连接的 url 参数格式为:
jdbc:mysql://服务器地址:端口/数据库名?参数名=参数值
charsetEncoding:设置字符集和编码方式
useSSL:数据是否进行加密传输
接着,和数据库服务器建立连接:
Connection connection = dataSource.getConnection();
在建立连接的过程中可能会出错(抛出异常),如 url 不正确、用户名有误、密码错误等,需要我们进行处理
然后,就可以构造 SQL 语句并执行了
// 构造 SQLString sql = "insert into class values (4, '四班')";PreparedStatement statement = connection.prepareStatement(sql);// 执行 SQLint result = statement.executeUpdate();// 查看执行结果System.out.println(result);
最后,别忘记释放资源:
statement.close();
connection.close();
上述完整代码:
public class Test {public static void main(String[] args) throws SQLException {// 构造 DataSourseDataSource dataSource = new MysqlDataSource();((MysqlDataSource) dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false");((MysqlDataSource) dataSource).setUser("root");((MysqlDataSource) dataSource).setPassword("123456");// 建立连接Connection connection = dataSource.getConnection();// 构造 SQLString sql = "insert into class values (4, '四班')";PreparedStatement statement = connection.prepareStatement(sql);// 执行 SQLint result = statement.executeUpdate();// 查看执行结果System.out.println(result);// 执行完毕,释放资源statement.close();connection.close();}
}
总结一下 JDBC 的使用步骤:
1. 创建数据库连接 Connection
2. 创建操作命令
3. 执行SQL
4. 若进行查询操作,处理结果集 ResultSet
5. 释放资源
在通过 JDBC 对数据库进行操作时,需要使用其提供的 API 进行统一处理,因此,我们来进一步学习 JDBC API
常用接口和类
Connection
Connection 接口用于与数据库建立连接,由数据库提供,获取 Connection 对象通常有两种方式:
(1)通过 DriverManager(驱动管理类)的静态方法获取
// 数据库连接信息
String url = "jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false";
String user = "root";
String password = "123456";
// 加载 JDBC 驱动
Class.forName("com.mysql.jdbc.Driver");
// 创建数据库连接
Connection connection = DriverManager.getConnection(url, user, password);
(2)通过 DataSource(数据源)对象获取
// 构造 DataSourse
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource) dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false");
((MysqlDataSource) dataSource).setUser("root");
((MysqlDataSource) dataSource).setPassword("phantom5170&");
// 建立连接
Connection connection = dataSource.getConnection();
上述两种方式的区别为:
使用 DriverManager 类获取的 Connection 连接,是无法重复利用的,每次使用完后释放资源时,通过 connection.close() 关闭物理连接
DataSource 提供连接池支持,连接池在初始化创建时将创建一定数量的数据库连接,这些连接是可以复用的,每次使用完数据库连接,释放资源调用 connection.close() 都是将 Connection 连接对象回收
Statement
Statement 对象主要是将 SQL 语句发送到数据库中,JDBC API 中主要提供了三种 Statement 对象
Statement:通常用于执行不带参数的简单 SQL 语句
PreparedStatement:用于执行带或不带参数的SQL语句,SQL 语句会进行预编译,PreparedStatement 的执行速度快于 Statement
CallableStatement:用于执行数据库存储过程中的调用
其中,PreparedStatement 是最常用的,接下来,我们就来继续学习 PreparedStatement
什么是预编译?
当数据库服务器收到一条SQL语句之后,会:
先解析语法和语义,校验 SQL 语句是否正确
再优化 SQL 制定执行计划
执行并返回结果
若一条 SQL 执行上述流程,就称为 Immediate Statements(即时SQL)
而 预编译 SQL 则会在编译一次之后将 SQL 语句缓存起来,后面再执行这条语句时,就不会再进行编译,省去了解析优化等过程
预编译 SQL 可以提高执行效率,因为 SQL 语句只需编译一次,然后可以多次执行,避免了重复编译的开销。预编译 SQL 通常用于需要频繁执行的 SQL 语句,如重复执行的查询或更新操作
即:
Immediate Statements(即时SQL):每次执行 SQL 语句时,数据库管理系统都会即时地进行语法分析、语义分析、优化和执行,而不是提前进行编译和优化。每次执行即时 SQL 语句都会有一定的性能开销,因为需要进行完整的编译和优化过程。
预编译 SQL(Prepared SQL):在预编译阶段,数据库管理系统(DBMS)会对 SQL 语句进行编译,生成执行计划,并将其存储在数据库中,而不是在每次执行时重新编译。在执行阶段,应用程序发送带有占位符的预编译 SQL 语句给 DBMS,DBMS 根据预编译的执行计划执行 SQL,并将实际参数传递给占位符,以生成最终的查询结果
如何向 SQL 语句传递参数?
通常使用 字符串 来构造 SQL 语句,如 String sql = "insert into class values (4, '四班')" 此时语句中的参数是固定的,但是若我们需要让用户来指定参数,此时,该如何传递参数呢?
PreparedStatement 可以使用 ? 作为占位符,后续再进行参数的指定:
// 构造 SQL
String sql = "insert into class values (?, ?)";
// 将 string sql 转换为语句对象
PreparedStatement statement = connection.prepareStatement(sql);
// 获取输入的参数
Scanner scanner = new Scanner(System.in);
System.out.print("请输入班级id:>");
int classId = scanner.nextInt();
System.out.print("请输入班级名称:>");
String className = scanner.next();
// 设置 sql 参数
statement.setInt(1, classId);
statement.setString(2, className);
先使用 ? 对要进行传递的参数进行占位,后续再设置参数的值
paramenterIndex:参数下标
x:参数的值
PreparedStatement 中主要使用以下两种执行SQL的方法:
executeQuery():通常用于执行 select 语句,执行后返回一个结果集(ResultSet)
executeUpdate():通常用于执行 update、insert 和 delete 语句,返回受影响的行数
我们对执行上述构造的 sql:
// 执行 SQL
int result = statement.executeUpdate();
// 查看执行结果
System.out.println(result);
返回结果为1,表示执行的语句影响了一行,说明插入操作成功
ResultSet
ResultSet(结果集) 对象表示符合 SQL 语句的所有行
我们进行查询操作:
String selectSql = "select * from employees";
PreparedStatement statement = connection.prepareStatement(sql);
ResultSet resultSet = statement.executeQuery();
ResultSet 中的数据是一行一行排列的,每行有多个字段,有一个记录指针,指针所指的数据行为当前数据行
我们只能操作当前的数据行,若我们想要获取某一行,就需要使用 ResultSet 的 next() 方法找到这一行,若我们想要得到 ResultSet 中的所有记录,就需要使用 while 循环
while (resultSet.next()) {
}
通过其提供的 get 方法来对行中的数据进行访问:
例如:
while (resultSet.next()) {int id = resultSet.getInt("id");String name = resultSet.getString("name");int managerId = resultSet.getInt("manager_id");System.out.println("id: " + id + " name: " + name + " manager_id: " + managerId);}
注意:结果集也需要释放
为了保证资源能够释放,我们可以将它们放到 finally 中
public class Test {public static void main(String[] args) {Connection connection = null;PreparedStatement statement = null;ResultSet resultSet = null;try {// 构造 DataSourseDataSource dataSource = new MysqlDataSource();((MysqlDataSource) dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false");((MysqlDataSource) dataSource).setUser("root");((MysqlDataSource) dataSource).setPassword("phantom5170&");// 建立连接connection = dataSource.getConnection();// 构造 sqlString sql = "select * from employees";statement = connection.prepareStatement(sql);resultSet = statement.executeQuery();// 查看结果集while (resultSet.next()) {int id = resultSet.getInt("id");String name = resultSet.getString("name");int managerId = resultSet.getInt("manager_id");System.out.println("id: " + id + " name: " + name + " manager_id: " + managerId);}} catch (SQLException e) {e.printStackTrace();} finally {// 执行完毕,释放资源if(resultSet != null) {try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if(statement != null) {try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if(connection != null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}}
}
使用总结
JDBC 使用步骤:
1. 创建数据库连接Connection
DriverManager 创建
DataSource 获取
2. 创建操作命令Statement
Statement
PreparedStatement
CallableStatement
3. 使用操作命令来执行SQL
executeQuery()
executeUpdate()
4. 处理结果集 Result
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
...
}
5. 释放资源
// 执行完毕,释放资源
if(resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}