【JavaEE基础学习打卡05】JDBC之基本入门就可以了
目录
- 前言
- 一、JDBC学习前说明
- 1.Java SE中JDBC
- 2.JDBC版本
- 二、JDBC基本概念
- 1.JDBC原理
- 2.JDBC组件
- 三、JDBC基本编程步骤
- 1.JDBC操作的数据库准备
- 2.JDBC操作数据库表步骤
- 四、代码优化
- 1.简单优化
- 2.with-resources探讨
- 总结
前言
📜 本系列教程适用于JavaWeb初学者、爱好者,小白白。我们的天赋并不高,可贵在努力,坚持不放弃。坚信量最终引发质变,厚积薄发。
🚀 文中白话居多,尽量以小白视角呈现,帮助大家快速入门。
🎅 我是 蜗牛老师,之前网名是 Ongoing蜗牛,人如其名,干啥都慢,所以更新也慢。希望大家多多支持,让我动力十足!
本文主要讲述 JDBC 编程基本步骤,带领大家基本入门,通过 JDBC API 实现与数据库连接,并简单查询数据库表中的数据到 Java 中。但是总想把知识点的前前后后都说清楚,所以整体篇幅有点长。
一、JDBC学习前说明
1.Java SE中JDBC
大家还记得我们说过 Java EE 中有 JDBC API,我们一起再回顾一下。
Java 数据库连接 API
Java 数据库连接(JDBC) API 允许从Java编程语言方法调用 SQL 命令。当使用会话 Bean 访问数据库时,可以在企业 Bean 中使用 JDBC API。还可以使用来自 Servlet 或 JSP 页面的 JDBC API 直接访问数据库,而无需通过企业 Bean。JDBC API 有两个部分:
- 应用程序组件用来访问数据库的应用程序级接口
- 将 JDBC 驱动程序附加到 Java EE 平台的服务提供程序接口
Java EE 8 平台需要 JDBC 4.1。
Java EE 中的 JDBC API 其实是 Java SE 中集成库中的 API,JDBC API 由两个包组成:
java.sql
javax.sql
当我们下载 Java 平台标准版(Java SE) 时,将自动获得这两个包。
2.JDBC版本
Java EE 8 平台需要 JDBC 4.1。那么 JDBC 4.1 其实是 Java SE 7 版本中增强的内容。
Java SE7 中 JDBC 4.1 引入了以下特性:
- 使用
try-with-resources
语句自动关闭Connection
、ResultSet
和statement
类型的资源的能力。 - RowSet 1.1:引入
RowSetFactory
接口和RowSetProvider
类,它们能够创建 JDBC 驱动程序支持的所有类型的行集。
Java SE8 中 JDBC 4.2 引入了以下特性:
- 增加了对
REF_CURSOR
的支持。 - 增加了
java.sql.DriverAction
接口。 - 在
DriverManager
类中增加了对deregisterDriver
方法的安全检查。 - 新增
java.sql.SQLType
接口。 - 增加
java.sql.JDBCType
枚举。 - 增加对大更新计数的支持。
- 对现有接口的更改。
- Rowset 1.2:列出 JDBC Rowset 的增强。
大家也看到了,Java EE 8 使用的是 Java SE 7 中 JDBC 4.1,而 Java SE 8 中的 JDBC 版本是4.2,对于Java SE 9 中的 JDBC 版本是4.3,每个 JDBC 版本都有功能的增强,但是对于目前的我们来说,这些新增的特性没必要学习,我们需要是对 JDBC 有个基本入门即可。因为日后几乎不会使用原始的 JDBC 进行编程,它仅仅是我们学习持久层框架的基础而已,因为这些框架的底层就是 JDBC API。
二、JDBC基本概念
Java Database Connectivity,Java 数据库连接(Database 数据库,Connectivity 连通、联接),简称 JDBC。是 Java 应用程序与各种数据库和数据源之间连接的 API(Application Programming Interface,应用程序编程接口)。
Java 数据库连接(JDBC) API 提供了来自 Java 编程语言的通用数据访问。使用 JDBC API,几乎可以访问任何数据源,可以使用基本的 JDBC API 来创建表、向表中插入值、查询表、检索查询结果以及更新表。
1.JDBC原理
其实我们知道即使是关系型数据库,市面上也有很多种,比如 MySQL、Oracle 等,JDBC API 如何做到通用呢?也就是说如何做到访问不同的数据库呢?
其实要在特定的数据库管理系统中使用 JDBC API,需要一个基于 JDBC 技术的驱动程序来在 JDBC 技术和数据库之间进行中介。根据各种因素,驱动程序可以完全用 Java 编程语言编写,也可以混合使用 Java 编程语言和 Java 本机接口(Java Native Interface, JNI)本地方法编写。
简单理解就是 JDBC API 是 Java 程序连接数据库的标准接口,具体说各个数据库想要通过 Java 编程使用,就需要由各个数据库厂商自己按照 JDBC 标准提供具体实现。
来一张图进行说明吧
JDBC 为多种关系数据库提供了统一访问方式,作为特定厂商数据库访问 API 的一种高级抽象,它主要包含一些通用的接口类。然后各厂商提供自己的 JDBC 实现,也就是 JDBC 驱动程序。最后程序员就可以通过 JDBC 驱动程序实现该数据库的操作了。
2.JDBC组件
这里简单介绍一下 JDBC 组件,大家了解即可。
JDBC 包括四个组件:
- JDBC API: JDBC API 提供了对 Java 编程语言中的关系数据的编程访问。使用 JDBC API,应用程序可以执行 SQL 语句、检索结果并将更改传播回底层数据源。JDBC API 还可以与分布式异构环境中的多个数据源进行交互。JDBC API 是 Java 平台的一部分,该平台包括 Java 标准版(Java SE)和 Java 企业版(Java EE)。JDBC API 两个包:
java.sql
和javax.sql
。这两个包都包含在 Java SE 和 Java EE 平台中。 - JDBC 驱动管理器: JDBC 驱动管理器类定义了可以将 Java 应用程序连接到 JDBC 驱动程序的对象。传统上,
DriverManager
一直是 JDBC 体系结构的支柱。它是相当小和简单。 - JDBC 测试套件: JDBC 驱动程序测试套件帮助确定 JDBC 驱动程序将运行的程序。这些测试并不全面或详尽,但它们确实测试了 JDBC API 中的许多重要特性。
- JDBC-ODBC桥: Java 软件桥通过 ODBC 驱动程序提供 JDBC 访问。注意,需要将 ODBC 二进制代码加载到使用该驱动程序的每台客户机上。因此,ODBC 驱动程序最适合于客户端安装不是主要问题的企业网络,或者适合于用 Java 在三层体系结构中编写的应用程序服务器代码。
三、JDBC基本编程步骤
前面大家尽量理解就好,本章节就是重点了,我们要使用 JDBC 进行实操了。
JDBC 帮助可以编写管理以下三种编程活动的 Java 应用程序:
- 连接到数据源,如数据库。
- 向数据库发送查询和更新语句。
- 检索并处理从数据库接收到的结果。
JDBC 可以做的这三件事,就是 JDBC 编程的大致操作步骤。
1.JDBC操作的数据库准备
我们打开客户端 MySQL Workbench,连接到本地 MySQL 服务器。接下来图形界面操作起来吧。
创建数据库 test_jdbc
数据库中创建 teacher
表
给 teacher
表中添加数据,点击图中红色框中的图标,在数据界面添加数据。
2.JDBC操作数据库表步骤
打开 IDEA,创建一个普通的 Java 项目。
在 src
下新建 Test
类,生成主函数 main()
方法
做好以上准备后,我们来看 JDBC 详细编程步骤:
- 引入驱动并加载
- 建立数据库连接
- 创建语句对象
- 执行SQL语句并返回结果
- 处理结果
- 关闭资源
我们看具体演示:
第一步:将数据库驱动程序引入到项目,并在程序中加载
JDBC 驱动程序是由数据库厂商提供的,这里使用了 MySQL 数据库,所以我们可以到 MySQL 官网下载该驱动,也就是一个 jar 包。
下载步骤大家可以参考这篇文章:https://blog.csdn.net/Li_Ya_Fei/article/details/104583417
我本地的 MySQL 版本是8.0.30,所以从官网下载了对应版本的驱动 jar包。下载后的 jar包如下图所示:
在 test-jdbc
项目中新建 lib
文件夹(习惯性将 jar 包统一放在此文件夹管理,lib
也就代表 Library,库),将 jar 包复制进来,这时该 jar 只是放在了 lib
文件夹下,并没有引入到项目中,需要选中 jar 包右键,在菜单中点击 Add as Library...
,将其添加了项目库中。
添加后,是可以查看其源代码的。
将 MySQL 数据库驱动引入到项目后,如何在程序中加载呢?
我们使用 Class.forName(‘驱动路径’)
去动态加载 MySQL 的 JDBC 驱动实现。它的作用是加载指定路径下的 MySQL JDBC 驱动,并将其注册到 DriverManager
中,以便后续的数据库连接操作可以使用该驱动。
/*** 敲入main,根据提示自动生成主函数main()方法* @param args*/
public static void main(String[] args) {try {// ①动态加载指定路径下的 MySQL JDBC驱动,将其注册到 DriverManager中。Class.forName("com.mysql.cj.jdbc.Driver");} catch (ClassNotFoundException e) {// ①加载的类找不到时,会抛出 ClassNotFoundException异常。e.printStackTrace();}
}
需要注意的是,这段代码必须在其他数据库操作之前执行,以确保在使用其他数据库操作之前已经正确加载了 MySQL 的 JDBC 驱动。如果该驱动类不存在或无法被加载,则会抛出 ClassNotFoundException
异常,打印异常堆栈信息。
这里只需要记住 MySQL JDBC 驱动的位置是 com.mysql.cj.jdbc.Driver
。我们可以直接找到该类。
我们顺便看一眼源码,其实还挺简单的。
它定义了一个名为 Driver
的类,该类继承自 NonRegisteringDriver
并实现了 java.sql.Driver
接口。足以说明该类是 JDBC API 的一个实现。在静态代码块中,尝试使用 DriverManager.registerDriver()
方法注册这个驱动。如果注册失败,将抛出一个运行时异常。
第二步:建立 JDBC 和数据库之前的 Connection 连接
上一步将 MySQL JDBC 驱动注册到 DriverManager
,从字面我们知道DriverManager
就是驱动的管理器,管理诸多驱动程序。所以我们建立与数据库的连接,要从 DriverManager
获得。使用DriverManager.getConnection(‘连接信息’)
,方法中需要填写连接信息,我们使用客户端也需要先填写连接信息才能操作数据库,这里也是一样的,也需要有连接信息,才能连接到数据库。
我们先上代码,然后再解释说明。
/*** 敲入main,根据提示自动生成主函数main()方法* @param args*/
public static void main(String[] args) {try {// ①动态加载指定路径下的 MySQL JDBC驱动,将其注册到 DriverManager中。Class.forName("com.mysql.cj.jdbc.Driver");// ②建立到给定数据库 URL的连接。Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test_jdbc?serverTimezone=Asia/Shanghai", "root", "root");} catch (ClassNotFoundException e) {// ①加载的类找不到时,会抛出 ClassNotFoundException异常。e.printStackTrace();} catch (SQLException throwables) {// ②如果数据库访问错误发生或 url为空时,会抛出 SQLException异常。throwables.printStackTrace();}
}
在上述代码中,②处用于建立到 MySQL 数据库的连接,它使用了DriverManager.getConnection()
方法来获取一个与指定 URL 相对应的数据库连接对象。该方法有 SQLException
这个异常需要处理。在代码中,DriverManager.getConnection()
方法接受三个参数:
- 第一个参数是数据库的 URL,指定了要连接的数据库的位置和端口号。在这个例子中,URL 为
jdbc:mysql://127.0.0.1:3306/test_jdbc?serverTimezone=Asia/Shanghai
,表示连接到本地主机(127.0.0.1)的 MySQL 服务器上,端口号为3306,数据库名为test_jdbc
,并设置了时区为Asia/Shanghai
。注意,不设置时区是会报错的哦! - 第二个参数是用于连接数据库的用户名,这里设置为"root"。
- 第三个参数是用于连接数据库的密码,这里也设置为"root"。数据库密码是我们安装 MySQL 服务器时设置的密码哦。
该方法返回 Connection
对象,我们接收一下就可以,Connection
对象就是与 MySQL 数据库的连接(会话)。我们可以在连接的上下文中执行 SQL 语句并返回结果。
这里大家其实需要注意 MySQL 数据库 URL 的写法,虽然现在网上查询 URL 很方便,但是自己能记忆最好。
第三步:创建 Statement 对象,用于向数据库发送 SQL 语句
这里使用 Connection
连接对象中的 createStatement()
方法创建 Statement
语句对象,用于向数据库发送 SQL 语句。Statement
用于实现不带参数的简单 SQL 语句。
/*** 敲入main,根据提示自动生成主函数main()方法* @param args*/
public static void main(String[] args) {try {// ①动态加载指定路径下的MySQL JDBC驱动,将其注册到DriverManager中。Class.forName("com.mysql.cj.jdbc.Driver");// ②建立到给定数据库URL的连接。Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test_jdbc?serverTimezone=Asia/Shanghai", "root", "root");// ③创建一个Statement对象,用于向数据库发送SQL语句。Statement statement = connection.createStatement();} catch (ClassNotFoundException e) {// ①加载的类找不到时,会抛出ClassNotFoundException异常。e.printStackTrace();} catch (SQLException throwables) {// ②如果数据库访问错误发生或url为空时,会抛出SQLException异常。throwables.printStackTrace();}
}
大家看上述代码的③处,创建了 Statement
对象后赋值给 statement
变量。
第四步:执行 SQL 语句并处理返回结果
Statement
用于执行不带参数的简单的静态 SQL 语句,并返回其产生的结果。我们可以看一下 Statement
这个类提供的方法:
方法有很多,对于入门的我们来说掌握前两个即可。
第一个 executeQuery()
,执行 select
查询语句,返回结果集 ResultSet
。execute
是执行的意思,query
就是查询的意思。这个两个单词在编程中经常见。
/*** 执行给定的SQL语句,该语句返回单个ResultSet对象。* 参数:sql—发送到数据库的sql语句,通常是静态sql SELECT语句* 返回:一个ResultSet对象,其中包含给定查询产生的数据;没有空* */
ResultSet executeQuery(String sql) throws SQLException;
第二个 executeUpdate()
,执行更新操作,比如 insert
、update
或 delete
语句,返回执行的行数。update
就是更新的意思。这个单词在编程中也经常见。
/*** 执行给定的SQL语句,该语句可以是INSERT、UPDATE或DELETE语句,也可以是不返回任何结果的SQL语句,例如SQL DDL语句。* 参数:sql—sql数据操作语言(DML)语句,如INSERT, UPDATE或DELETE;或者是不返回任何结果的SQL语句,比如DDL语句。* 返回:(1)SQL数据操作语言(DML)语句的行数,或(2)不返回任何结果的SQL语句的0*/
int executeUpdate(String sql) throws SQLException;
接下来我们使用 executeQuery()
方法,查询 teacher
表中的数据,上代码。
/*** 敲入main,根据提示自动生成主函数main()方法* @param args*/
public static void main(String[] args) {try {// ①动态加载指定路径下的MySQL JDBC驱动,将其注册到DriverManager中。Class.forName("com.mysql.cj.jdbc.Driver");// ②建立到给定数据库URL的连接。Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test_jdbc?serverTimezone=Asia/Shanghai", "root", "root");// ③创建一个Statement对象,用于向数据库发送SQL语句。Statement statement = connection.createStatement();// ④执行SQL语句并返回结果ResultSet resultSet = statement.executeQuery("select * from teacher");} catch (ClassNotFoundException e) {// ①加载的类找不到时,会抛出ClassNotFoundException异常。e.printStackTrace();} catch (SQLException throwables) {// ②如果数据库访问错误发生或url为空时,会抛出SQLException异常。throwables.printStackTrace();}
}
上述代码④处,调用 Statement
对象中的 executeQuery()
执行 SQL 语句select * from teacher
,查询 teacher
表中全部数据,注意没有结束 ;
号。将查询结果封装在 ResultSet
结果集,我们需要接收一下。
第五步:处理 SQL 执行的结果
处理结果集,也就是我们需要从 ResultSet
中将查询的数据取出来。通过游标访问对象中的数据。它就是 ResultSet
类中的 next()
。请注意,此游标不是数据库游标。此光标是指向对象中一行数据的指针。最初,光标位于第一行之前。大家仔细阅读下面⑤处代码。
/*** 敲入main,根据提示自动生成主函数main()方法* @param args*/
public static void main(String[] args) {try {// ①动态加载指定路径下的MySQL JDBC驱动,将其注册到DriverManager中。Class.forName("com.mysql.cj.jdbc.Driver");// ②建立到给定数据库URL的连接。Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test_jdbc?serverTimezone=Asia/Shanghai", "root", "root");// ③创建一个Statement对象,用于向数据库发送SQL语句。Statement statement = connection.createStatement();// ④执行SQL语句并返回结果ResultSet resultSet = statement.executeQuery("select * from teacher");// ⑤处理SQL语句执行的结果while(resultSet.next()){// 从结果集将当前行数据取出int id = resultSet.getInt("id");String name = resultSet.getString("name");String sex = resultSet.getString("sex");int age = resultSet.getInt(4);// 打印输出当前行数据System.out.println("id:" + id + ",name:" + name + ",sex:" + sex + ",age:" + age);}} catch (ClassNotFoundException e) {// ①加载的类找不到时,会抛出ClassNotFoundException异常。e.printStackTrace();} catch (SQLException throwables) {// ②如果数据库访问错误发生或url为空时,会抛出SQLException异常。throwables.printStackTrace();}
}
由于 select
语句查询的结果可能为多行,故使用 while
循环,条件就是 next()
方法,该方法返回 boolean
值。上面说过 ResultSet
游标最初定位在第一行之前,那么 while
循环中该方法的第一次调用 next
使第一行成为当前行,第二次调用将第二行作为当前行,依此类推。当对 next
方法的调用返回 false
时,游标定位在最后一行之后。
那么在循环体内,我们就可以将当前行数据取出,如何取出数据呢?ResultSet
类中提供了一系列方法。
取数据,我们使用 get
开头的方法,比如 getInt()
方法是取出某列的 int
类型数据,getString()
方法就是取出字符串类型数据。
我们可以看到 getInt()
方法有两个,这两个方法就是重载,方法重载(Overloading)是指在同一个类中,允许存在多个同名方法,但这些方法的参数列表必须不同。
获取其他类型数据也都有两个方法,它们的参数类型不同。
/*** 以Java编程语言的int形式检索此ResultSet对象当前行的指定列的值。* columnLabel—用SQL AS子句指定的列的标签。如果没有指定SQL AS子句,则标签是列的名称*/
int getInt(String columnLabel) throws SQLException;
/*** 以Java编程语言的int形式检索此ResultSet对象当前行的指定列的值。* columnIndex -第一列是1,第二列是2,…*/
int getInt(int columnIndex) throws SQLException;
简单来说第一个方法是根据列名获取数据,第二个方法是根据列号获取数据。哪种方式更好呢?当然是第一种根据列名,如果根据第几列获取,很容易搞混,而且代码不易维护。
第六步:关闭资源
当我们使用完对象后,调用其方法以立即释放它正在使用的资源。
/*** 敲入main,根据提示自动生成主函数main()方法* @param args*/
public static void main(String[] args) {try {// ①动态加载指定路径下的MySQL JDBC驱动,将其注册到DriverManager中。Class.forName("com.mysql.cj.jdbc.Driver");// ②建立到给定数据库URL的连接。Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test_jdbc?serverTimezone=Asia/Shanghai", "root", "root");// ③创建一个Statement对象,用于向数据库发送SQL语句。Statement statement = connection.createStatement();// ④执行SQL语句并返回结果ResultSet resultSet = statement.executeQuery("select * from teacher");// ⑤处理SQL语句执行的结果while(resultSet.next()){// 从结果集将当前行数据取出int id = resultSet.getInt("id");String name = resultSet.getString("name");String sex = resultSet.getString("sex");int age = resultSet.getInt(4);// 打印输出当前行数据System.out.println("id:" + id + ",name:" + name + ",sex:" + sex + ",age:" + age);}// ⑥关闭资源,关闭顺序:从里到外的原则,保证该资源确定不再使用后关闭resultSet.close();statement.close();connection.close();} catch (ClassNotFoundException e) {// ①加载的类找不到时,会抛出ClassNotFoundException异常。e.printStackTrace();} catch (SQLException throwables) {// ②如果数据库访问错误发生或url为空时,会抛出SQLException异常。throwables.printStackTrace();}
}
上述代码⑥处,调用了三个对象的 close()
方法来关闭我们使用的资源。这些资源在使用完毕之后是一定要进行关闭的,不然这些资源可能一致被占用。
到这里一个 JDBC 编程基本步骤就完成了,最后就是验证成果的时候了。我们运行程序,查看控制台是否会打印出 teacher
表中的数据。
四、代码优化
对 JDBC 编程基本步骤中的代码进行优化,有兴趣的可以看一下。
1.简单优化
主要优化的地方是将关闭资源操作放在 finally
块中,即程序无论正确执行还是抛出异常都要关闭资源。
/*** 敲入main,根据提示自动生成主函数main()方法* @param args*/
public static void main(String[] args) {// 将Connection、Statement、ResultSet对象变量提取至try...catch外Connection connection = null;Statement statement = null;ResultSet resultSet = null;try {// ①动态加载指定路径下的MySQL JDBC驱动,将其注册到DriverManager中。Class.forName("com.mysql.cj.jdbc.Driver");// ②建立到给定数据库URL的连接。connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test_jdbc?serverTimezone=Asia/Shanghai", "root", "root");// ③创建一个Statement对象,用于向数据库发送SQL语句。statement = connection.createStatement();// ④执行SQL语句并返回结果resultSet = statement.executeQuery("select * from teacher");// ⑤处理SQL语句执行的结果while(resultSet.next()){// 从结果集将当前行数据取出int id = resultSet.getInt("id");String name = resultSet.getString("name");String sex = resultSet.getString("sex");int age = resultSet.getInt(4);// 打印输出当前行数据System.out.println("id:" + id + ",name:" + name + ",sex:" + sex + ",age:" + age);}} catch (ClassNotFoundException | SQLException e) {/* 异常合并到一起* ①加载的类找不到时,会抛出ClassNotFoundException异常。* ②如果数据库访问错误发生或url为空时,会抛出SQLException异常。*/e.printStackTrace();} finally {try {// ⑥关闭资源,关闭顺序:从里到外的原则,保证该资源确定不再使用if (resultSet != null) {resultSet.close();}if (statement != null) {statement.close();}if (connection != null) {connection.close();}} catch (SQLException throwables) {throwables.printStackTrace();}}
}
2.with-resources探讨
其实除了上述的简单优化,还可以使用 with-resources
来自动关闭资源。with-resources
是 Java 7 引入的一个新特性,用于自动管理资源的关闭。它允许在 try-with-resources
语句中声明需要关闭的资源,当 try
代码块执行完毕后,资源会自动被关闭,无需显式调用 close()
方法。使用 with-resources
可以简化代码,避免资源泄漏和手动关闭资源的繁琐操作。它适用于实现了 java.lang.AutoCloseable
接口的资源对象,包括文件流、数据库连接、网络连接等。
Connection
、Statement
和 ResultSet
都实现了 java.lang.AutoCloseable
接口,也就说这三个资源可以使用 with-resources
来自动关闭。需要注意的是,使用 with-resources
语句时,资源对象的初始化必须在 try
代码块之前完成。以下是示例代码:
try (FileInputStream fis = new FileInputStream("file.txt");BufferedReader br = new BufferedReader(new InputStreamReader(fis))) {String line;while ((line = br.readLine()) != null) {System.out.println(line);}
} catch (IOException e) {e.printStackTrace();
}
从代码中可以看出要关闭的资源在 try
的 ()
内初始化的,那对于咱们 JDBC 来说 Connection
、Statement
和 ResultSet
都在 try
的 ()
内初始化,感觉乱,并不舒服。所以我就想了想,没有去尝试。有兴趣的小伙伴可以尝试一下,对于 JDBC 关闭资源,with-resources
这个特性是不是有优势。
总结
Java EE 中关于 JDBC API,是使用 Java SE 中的 JDBC。
Java 提供一个标准的 JDBC 接口,也就是定义这一规范。然后由各数据库厂商负责实现。所以我们想用 Java 连接哪个数据库,就需要有哪个数据库的 JDBC 驱动程序。
JDBC 负责三件事:
- 连接到数据源,如数据库
- 向数据库发送查询和更新语句
- 检索并处理从数据库接收到的结果
JDBC 具体编程步骤:
- 引入驱动并加载
- 建立数据库连接
- 创建语句对象
- 执行SQL语句并返回结果
- 处理结果
- 关闭资源
只是看是学不会的,要赋予实际的行动——敲代码!
相关文章:
【JavaEE基础学习打卡05】JDBC之基本入门就可以了
目录 前言一、JDBC学习前说明1.Java SE中JDBC2.JDBC版本 二、JDBC基本概念1.JDBC原理2.JDBC组件 三、JDBC基本编程步骤1.JDBC操作的数据库准备2.JDBC操作数据库表步骤 四、代码优化1.简单优化2.with-resources探讨 总结 前言 📜 本系列教程适用于JavaWeb初学者、爱好…...
2023/8/16 华为云OCR识别驾驶证、行驶证
目录 一、 注册华为云账号开通识别驾驶证、行驶证服务 二、编写配置文件 2.1、配置秘钥 2.2、 编写配置工具类 三、接口测试 3.1、测试接口 3.2、结果 四、实际工作中遇到的问题 4.1、前端传值问题 4.2、后端获取数据问题 4.3、使用openfeign调用接口报错 4.3、前端显示问题…...
【Java开发】 Mybatis-Plus 07:创建时间、更新时间自动添加
Mybatis-Plus 可以通过配置实体类的注解来自动添加创建时间和更新时间,这可以减轻一定的开发量。 1 在实体类中添加注解 public class User {TableId(type IdType.AUTO)private Long id;private String username;private String password;TableField(fill FieldF…...
解决vue2项目在IE11浏览器中无画面的兼容问题
解决vue2项目在IE11浏览器中无画面的兼容问题 背景介绍当前网上能找打的教程 背景介绍 当前项目面临其他浏览器都可以运行,但是在IE11浏览器中出现白屏的现象,F12后台也没有报错,项目月底也要交付了。当前项目的vue版本为2.6.11,…...
信号
信号也是IPC中的一种,是和管道,消息队列,共享内存并列的概念。 本文参考: Linux中的信号_linux中信号_wolf鬼刀的博客-CSDN博客 Linux系统编程(信号处理 sigacation函数和sigqueue函数 )_花落已飘的博客-CSDN博客 Linu…...
产品经理的真实薪资有多少?今天带你看看
作为产品经理,除了需要拥有扎实的技术背景和出色的产品设计能力,还需具备出色的领导力和商业敏感度。因此,产品经理的薪资也越来越成为人们关注的话题。那么,一般来说,产品经理的薪资水平如何呢? 薪资多少…...
《一个操作系统的实现》windows用vm安装CentOS——从bochs环境搭建到第一个demo跑通
vm安装CentOS虚拟机带有桌面的版本。su输入密码123456。更新yum -y update 。一般已经安装好后面这2个工具:yum install -y net-tools wget。看下ip地址ifconfig,然后本地终端连接ssh root192.168.249.132输入密码即可,主要是为了复制网址方便…...
线程Thread
文章目录 一、概念1、进程2、线程3、CPU与线程的关系4、并行、并发5、线程的生命周期 二、创建1、继承Thread2、实现Runnable接口3、实现Callable接口 三、API1、获取运行使用的线程2、唯一标识3、线程名4、优先级5、是否处于活动状态6、守护线程7、join1、API2、有无join对比 …...
如何使用CSS实现一个渐变背景效果?
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 使用CSS实现渐变背景效果⭐ 线性渐变(Linear Gradient)⭐ 径向渐变(Radial Gradient)⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订…...
初始C语言(7)——详细讲解有关初阶指针的内容
系列文章目录 第一章 “C“浒传——初识C语言(1)(更适合初学者体质哦!) 第二章 初始C语言(2)——详细认识分支语句和循环语句以及他们的易错点 第三章 初阶C语言(3)——…...
ArcGIS Pro技术应用(暨基础入门、制图、空间分析、影像分析、三维建模、空间统计分析与建模、python融合、案例应用)
GIS是利用电子计算机及其外部设备,采集、存储、分析和描述整个或部分地球表面与空间信息系统。简单地讲,它是在一定的地域内,将地理空间信息和 一些与该地域地理信息相关的属性信息结合起来,达到对地理和属性信息的综合管理。GIS的…...
RISC-V公测平台发布 · 数据库在RISC-V服务器上的适配评估
前言 上一期讲到YCSB在RISC-V服务器上对MySQL进行性能测试(RISC-V公测平台发布 使用YCSB测试SG2042上的MySQL性能),在这一期文章中,我们继续深入讨论RISC-V数据库的应用。本期就继续利用HS-2平台来测试数据库软件在RISC-V服务器…...
UE5.2 LyraDemo源码阅读笔记(五)输入系统
Lyra里使用了增强输入系统,首先知道增强输入系统里的三个类型配置。 一、Input Actions (IA): 输入操作带来的变量,与玩家的输入组件绑定,回调里驱动玩家行为。 二、InputMappingContext(IMC):…...
线段树详解——影子宽度
OK,今天来讲一讲线段树~~ 线段树是什么线段树的实现线段树的时间复杂度线段树的应用线段树的节点结构其他操作和优化例题——影子宽度输入输出格式输入格式输出格式 输入输出样例输入样例输出样例 例题讲解 线段树是什么 线段树( S e g m e n t Segmen…...
使用R语言绘制折线图
写在前面 昨天我们分享了使用Python绘制折线图的教程,跟着NC学作图 | 使用python绘制折线图,考虑到很多同学基本不使用Python绘图。那么,我们也使用R语言复现此图形。 此外,在前期的教程中,我们基本没有分享过折线图的教程。因此,我们在这里也制作一期关于折线图的教程。…...
无涯教程-Perl - wantarray函数
描述 如果当前正在执行的函数的context正在寻找列表值,则此函数返回true。在标量context中返回false。 语法 以下是此函数的简单语法- wantarray返回值 如果没有context,则此函数返回undef;如果lvalue需要标量,则该函数返回0。 例 以下是显示其基本用法的示例…...
【gitkraken】gitkraken自动更新问题
GitKraken 会自动升级!一旦自动升级,你的 GitKraken 自然就不再是最后一个免费版 6.5.1 了。 在安装 GitKraken 之后,在你的安装目录(C:\Users\<用户名>\AppData\Local\gitkraken)下会有一个名为 Update.exe 的…...
《Java Web程序设计》试卷03
《Java Web程序设计》试卷03 课程编码: 301209 适用专业: 计算机应用(包括JAVA方向) 注 意 事 项 1、首先按要求在试卷标封处填写你所在的系(部)、专业、班级及学号和姓名; 2、仔细阅读各类题目的回答要求,…...
怎么查看小程序中的会员信息
商家通过查看会员信息,可以更好地了解用户,并为他们提供更个性化的服务和推荐。接下来,就将介绍如何查看会员信息。 商家在管理员后台->会员管理处,可以查看到会员列表。支持搜索会员的卡号、手机号和等级。还支持批量删除会员…...
网络安全—黑客—自学笔记
想自学网络安全(黑客技术)首先你得了解什么是网络安全!什么是黑客! 网络安全可以基于攻击和防御视角来分类,我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术,而“蓝队”、“安全运营”、“安全…...
深度解读波卡 2.0:多核、更有韧性、以应用为中心
本文基于 Polkadot 生态研究院整理,有所删节 随着波卡 1.0 的正式实现,波卡于 6 月 28 日至 29 日在哥本哈根举办了年度最重要的会议 Polkadot Decoded 2023,吸引了来自全球的行业专家、开发者和爱好者,共同探讨和分享波卡生态的…...
微服务中间件--Eureka注册中心
Eureka注册中心 a.eureka原理分析b.搭建eureka服务c.服务注册d.服务发现 a.eureka原理分析 1.每个服务启动时,将自动在eureka中注册服务信息 (每个服务每隔30秒发送一次的心跳续约,当某个服务没有发送时,eurekaServer将自动剔除该服务&#x…...
积跬步至千里 || 矩阵可视化
矩阵可视化 矩阵可以很方面地展示事物两两之间的关系,这种关系可以通过矩阵可视化的方式进行简单监控。 定义一个通用类 from matplotlib import pyplot as plt import seaborn as sns import numpy as np import pandas as pdclass matrix_monitor():def __init…...
zookeeper详细介绍
ZooKeeper是一个开源的分布式协调服务,具有以下一些关键特点: 数据模型 ZooKeeper的数据模型采用层次化的多叉树形结构,每个节点称为znode,类似于文件系统中的文件和目录。每个znode可以存储数据和控制信息。一致性保证 ZooKeeper通过ZAB协议,实现分布式环境下数据的强一致性,…...
面板市场趋势分析:价格上涨势头或将减缓 | 百能云芯
8月末,面板价格报价公布,市场研究机构TrendForce指出,电视面板今年以来已经上涨超过30%,虽然下游品牌商对于价格上涨提出了不同声音,但由于面板厂商采取了按需生产的策略,8月仍然出现了3~5%的价格上涨。Tre…...
JVM性能调优
java 如何跨平台,如何一次编译到处执行 是由于java在不同的jvm上编译,jvm在软件层面屏蔽不同操作系统在底层硬件与指令上的区别。 jvm 包括 new 的对象都是放在堆中 栈,给线程单独使用(线程私有),存储一个…...
【全链路追踪】XXL-JOB添加TraceID
文章目录 一、背景调用路径部署环境问题 二、方案三、Demo示例1、MDC2、RequestInterceptor3、HandlerInterceptor4、logback.xml 四、后续改进思路 一、背景 首先这个项目属于小型项目,由于人手以及时间限制,并未引入Skywalking等中间件来做调用链路追…...
[Unity]Lua本地时间、倒计时和正计时。
惯例,直接上代码: --正计时开始时的时间戳 self.begin_time os.time() --倒计时时长,01:30:00 self.countdown_time 5400 --是否开始计时 self.is_update_local_time true--Unity Update function time_transition:update_local_timer()i…...
探究HTTP API接口测试:工具、方法与自动化
本文将深入探讨HTTP API接口测试的重要性,并介绍了相关工具、方法以及自动化测试的实施,同时比较了HTTP和API接口测试的区别。从不同角度解析这一关键测试领域,帮助读者更好地理解和应用于实际项目中。 在如今数字化的世界中,软件…...
CSS中如何实现文字溢出省略号(text-overflow: ellipsis)效果?
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ CSS中如何实现文字溢出省略号(text-overflow: ellipsis)效果?⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 …...
wordpress开发视频教程/网页搜索引擎大全
一、痔疮用药市场规模 痔疮,是人类特有的常见病、多发病。据有关普查资料表明,痔疮等肛门直肠疾病的发病率为59.1%,痔疮占所有肛肠疾病中的87.25%,而其中又以内痔最为常见,占所有肛肠疾病的52.19%。男女均可得病&#…...
政府门户网站有哪些功能/欧美网站建设公司
14. Structuring your code 14.1 Using the “default” package 官方建议使用反向域名定义包结构,比如com.example.project 如果一个类没有被定义在一个包中,它会被放在一个default package中,当这个类应用ComponentScan EntityScan SpringB…...
百度云服务器做网站稳定吗/宁德市委书记
在编程过程中,经常会遇到四种修饰符来控制访问权限。之前对这个知识点没有研究过,一直是一知半解,每次遇到问题都模棱两可,不能给出一个确切的答案。近几天系统的看了看,也有了自己的一点心得体会。 正文: …...
国外设计师灵感网站/以图搜图百度识图
目录1. 两者区别的现象2. 部分代码解释2.1 open显示对话框2.1.1 对象方式创建2.1.2 指针方式创建2.2 exec显示对话框3. exec与open的区别4. 全部代码示例4.1 MainWindow.h4.2 MainWindow.cpp1. 两者区别的现象 注意:需要看下方的打印信息 2. 部分代码解释 2.1 open…...
网页的制作教案/手机seo快速排名
本文我们就来探索一下 Docker 的神秘世界,从零到一掌握 Docker 的基本原理与实践操作。别再守着前端那一亩三分地,是时候该开疆扩土了。 讲个故事 为了更好的理解 Docker 是什么,我们先来讲个故事: 我需要盖一个房子,于…...
做前端网站用什么工具/企业推广是做什么的
请问大家ndk中LOCAL_SHARED_LIBRARIES LOCAL_LDLIBS什么区别啊 我先是编译了一个.so 然后在此次编译的使用调用,请问用LOCAL_SHARED_LIBRARIES和LOCAL_LDLIBS什么区别啊,我用后者能编译通过,用前者不行呢,谢谢!&#…...