JDBC 编程

目录

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();
                }
            }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/54252.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

git学习【持续更新中。。。】

git学习【持续更新中。。。】 文章目录 git学习【持续更新中。。。】一、Git基本操作1.创建本地仓库2.配置本地仓库1.局部配置2.全局配置 3.认识工作区、暂存区、版本库4.添加文件5.修改文件6.版本回退7.撤销修改8.删除文件 二、Git分支管理1.理解分支2.创建、切换、合并分支3.…

AI 时代,大模型产业落地的八大思考

引言 在人工智能领域,大模型技术正逐渐成为推动行业进步的关键力量。随着技术的发展,大模型不仅在学术界引起了广泛的关注,也在产业界展现出巨大的应用潜力。然而,如何将这些强大的模型有效地应用到实际产业中,仍然是…

解决:Vue 中 debugger 不生效

目录 1,问题2,解决2.1,修改 webpack 配置2.2,修改浏览器设置 1,问题 在 Vue 项目中,可以使用 debugger 在浏览器中开启调试。但有时却不生效。 2,解决 2.1,修改 webpack 配置 通…

MySQL权限控制(DCL)

我的mysql里面的一些数据库和一些表 基本语法 1.查询权限 show grants for 用户名主机名;例子1:查询权限 show grants for heima%;2.授予权限 grant 权限列表 on 数据库名.表名 to 用户名主机名;例子2: 授予权限 grant all on itcast.* to heima%;…

Android Studio Menu制作

文章目录 一、创建菜单在Activity上新建onCreateOptionsMenu新建menu目录及资源文件新建Menu一级菜单在Activity上加载Menu测试效果 二、菜单点击事件 一、创建菜单 在Activity上新建onCreateOptionsMenu Overridepublic boolean onCreateOptionsMenu(Menu menu) {return supe…

Pytest配置文件pytest.ini如何编写生成日志文件?

1、新建pytest.ini文件 [pytest] log_clitrue log_leveLNOTSET log_format %(asctime)s %(levelname)s %(message)s %(filename)s %(funcName)s %(lineno)d log_date_format %Y-%m-%d %H:%M:%Slog_file ./logdata/log.log log_file_level info log_file_format %(asctime…

深入探究HTTP网络协议栈:互联网通信的基石

在我们日常使用互联网的过程中,HTTP(HyperText Transfer Protocol,超文本传输协议)扮演着至关重要的角色。无论是浏览网页、下载文件,还是进行在线购物,HTTP协议都在背后默默地支持着这些操作。今天&#x…

数据结构与算法——顺序表期末复习五大经典题型

目录 一:顺序表-移除元素 二:顺序表-删除有序数组中的重复项 三:顺序表-合并两个有序数组 四:顺序表-旋转数组 五:顺序表-数组形式的整数加法 一:顺序表-移除元素 题型链接:27. 移除元素 -…

玖逸云黑系统源码 v1.3.0全解无后门 +搭建教程

功能带有卡密生成和添加黑名单等,反正功能也不是很多具体的自己看程序截图即可。 搭建教程 完成 1.我们先添加一个站点 2.PHP选择7.3 3.上传源码解压 4.导入数据库 5.配置数据库信息config.php 源码下载:https://download.csdn.net/download/m0_6…

10年408考研真题-数据结构

23.[2010统考真题]若元素 a,b,c,d,e,f 依次进栈,允许进栈、退栈操作交替进行,但不允许连续3次进行退栈操作,不可能得到的出栈序列是(D)。 A.dcebfa B.cbdaef C.bcaefd D.afedcb 解析:直接看D选项&#xff0c…

VUE实现刻度尺进度条

一、如下图所示效果&#xff1a; 运行后入下图所示效果&#xff1a; 实现原理是用div画图并动态改变进度&#xff0c; 二、div源码 <div style"width: 100%;"><div class"sdg_title" style"height: 35px;"><!--对话组[{{ dialo…

用Python画一个五星红旗

#codingutf-8 import turtle import mathdef draw_polygon(aTurtle, size50, n3): 绘制正多边形args:aTurtle: turtle对象实例size: int类型&#xff0c;正多边形的边长n: int类型&#xff0c;是几边形 for i in range(n):aTurtle.forward(size)aTurtle.left(360.0/n)de…

Linux--守护进程与会话

进程组 概念 进程组就是一个或多个进程的集合。 一个进程组可以包含多个进程。 下面我们通过一句简单的命令行来展示&#xff1a; 为什么会有进程组&#xff1f; 批量操作&#xff1a;进程组允许将多个进程组织在一起&#xff0c;形成一个逻辑上的整体。当需要对多个进程…

下载Kafka 3.0.0教程

1、Kafka 3.0.0下载地址 Apache Kafka 2、往下拉&#xff0c;查找3.0.0版本点击下载

【C++前后缀分解 降维】2906. 构造乘积矩阵|2074

前后缀分解 C前后缀分解 LeetCode2906. 构造乘积矩阵 给你一个下标从 0 开始、大小为 n * m 的二维整数矩阵 grid &#xff0c;定义一个下标从 0 开始、大小为 n * m 的的二维矩阵 p。如果满足以下条件&#xff0c;则称 p 为 grid 的 乘积矩阵 &#xff1a; 对于每个元素 p[…

数据结构之‘栈’

文章目录 1.简介2. 栈的初始化和销毁3. 进栈和出栈3.1 进栈3.2 出栈3.3 栈的打印 1.简介 一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行&#xff08;数据插入和删除操作&#xff09;的一端称为栈顶&#xff0c;另一端称为栈底。压栈&#xf…

C语言之预处理详解(完结撒花)

目录 前言 一、预定义符号 二、#define 定义常量 三、#define定义宏 四、宏与函数的对比 五、#和## 运算符 六、命名约定 七、#undef 八、条件编译 九、头文件的包含 总结 前言 本文为我的C语言系列的最后一篇文章&#xff0c;主要讲述了#define定义和宏、#和##运算符、各种条件…

W25QXX系列Flash存储器模块驱动代码

目录 W25QXX简介 硬件电路 W25Q128框图 Flash操作注意事项 驱动代码 W25QXX.h W25QXX.c W25QXX简介 W25Qxx系列是一种低成本、小型化、使用简单的非易失性存储器&#xff0c;常应用于数据存储、字库存储、固件程序存储等场景 存储介质&#xff1a;Nor Flash&#xff0…

算法入门-贪心1

第八部分&#xff1a;贪心 409.最长回文串&#xff08;简单&#xff09; 给定一个包含大写字母和小写字母的字符串 s &#xff0c;返回通过这些字母构造成的最长的回文串 的长度。 在构造过程中&#xff0c;请注意 区分大小写 。比如 "Aa" 不能当做一个回文字符串…

如何通过 PhantomJS 模拟用户行为抓取动态网页内容

引言 随着网页技术的不断进步&#xff0c;JavaScript 动态加载内容已成为网站设计的新常态&#xff0c;这对传统的静态网页抓取方法提出了挑战。为了应对这一挑战&#xff0c;PhantomJS 作为一个无头浏览器&#xff0c;能够模拟用户行为并执行 JavaScript&#xff0c;成为了获…