【JavaEE基础学习打卡05】JDBC之基本入门就可以了

目录

  • 前言
  • 一、JDBC学习前说明
  • 二、JDBC基本概念
  • 三、JDBC基本编程步骤
    • 1.JDBC操作的数据库准备
    • 2.JDBC操作数据库表步骤
  • 四、代码优化
    • 1.简单优化
    • 2.with-resources探讨
  • 总结


前言

📜 本系列教程适用于JavaWeb初学者、爱好者,小白白。我们的天赋并不高,可贵在努力,坚持不放弃。坚信量最终引发质变,厚积薄发。
🚀 文中白话居多,尽量以小白视角呈现,帮助大家快速入门。
🎅 我是 蜗牛老师,之前网名是 Ongoing蜗牛,人如其名,干啥都慢,所以更新也慢。希望大家多多支持,让我动力十足!

本文主要讲述 JDBC 编程基本步骤,带领大家基本入门,通过 JDBC API 实现与数据库连接,并简单查询数据库表中的数据到 Java 中。但是总想把知识点的前前后后都说清楚,所以整体篇幅有点长。


JDBC_12">一、JDBC学习前说明

JDBC_13">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) 时,将自动获得这两个包。

JDBC_31">2.JDBC版本

Java EE 8 平台需要 JDBC 4.1。那么 JDBC 4.1 其实是 Java SE 7 版本中增强的内容。

Java SE7 中 JDBC 4.1 引入了以下特性:

  • 使用 try-with-resources 语句自动关闭 ConnectionResultSetstatement 类型的资源的能力。
  • 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_50">二、JDBC基本概念

Java Database Connectivity,Java 数据库连接(Database 数据库,Connectivity 连通、联接),简称 JDBC。是 Java 应用程序与各种数据库和数据源之间连接的 API(Application Programming Interface,应用程序编程接口)。

Java 数据库连接(JDBC) API 提供了来自 Java 编程语言的通用数据访问。使用 JDBC API,几乎可以访问任何数据源,可以使用基本的 JDBC API 来创建表、向表中插入值、查询表、检索查询结果以及更新表。

JDBC_55">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 驱动程序实现该数据库的操作了。

JDBC_67">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.sqljavax.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_76">三、JDBC基本编程步骤

前面大家尽量理解就好,本章节就是重点了,我们要使用 JDBC 进行实操了。

JDBC 帮助可以编写管理以下三种编程活动的 Java 应用程序:

  1. 连接到数据源,如数据库。
  2. 向数据库发送查询和更新语句。
  3. 检索并处理从数据库接收到的结果。

JDBC 可以做的这三件事,就是 JDBC 编程的大致操作步骤。

JDBC_87">1.JDBC操作的数据库准备

我们打开客户端 MySQL Workbench,连接到本地 MySQL 服务器。接下来图形界面操作起来吧。

创建数据库 test_jdbc
在这里插入图片描述

数据库中创建 teacher

在这里插入图片描述

teacher 表中添加数据,点击图中红色框中的图标,在数据界面添加数据。

在这里插入图片描述

JDBC_101">2.JDBC操作数据库表步骤

打开 IDEA,创建一个普通的 Java 项目。

在这里插入图片描述

src 下新建 Test 类,生成主函数 main() 方法

在这里插入图片描述

做好以上准备后,我们来看 JDBC 详细编程步骤:

  1. 引入驱动并加载
  2. 建立数据库连接
  3. 创建语句对象
  4. 执行SQL语句并返回结果
  5. 处理结果
  6. 关闭资源

我们看具体演示:

第一步:将数据库驱动程序引入到项目,并在程序中加载

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 查询语句,返回结果集 ResultSetexecute 是执行的意思,query 就是查询的意思。这个两个单词在编程中经常见。

/**
 * 执行给定的SQL语句,该语句返回单个ResultSet对象。
 * 参数:sql—发送到数据库的sql语句,通常是静态sql SELECT语句
 * 返回:一个ResultSet对象,其中包含给定查询产生的数据;没有空
 * 
 */
ResultSet executeQuery(String sql) throws SQLException;

第二个 executeUpdate(),执行更新操作,比如 insertupdatedelete 语句,返回执行的行数。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 接口的资源对象,包括文件流、数据库连接、网络连接等。

ConnectionStatementResultSet都实现了 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 来说 ConnectionStatementResultSet 都在 try() 内初始化,感觉乱,并不舒服。所以我就想了想,没有去尝试。有兴趣的小伙伴可以尝试一下,对于 JDBC 关闭资源,with-resources 这个特性是不是有优势。


总结

Java EE 中关于 JDBC API,是使用 Java SE 中的 JDBC

Java 提供一个标准的 JDBC 接口,也就是定义这一规范。然后由各数据库厂商负责实现。所以我们想用 Java 连接哪个数据库,就需要有哪个数据库的 JDBC 驱动程序。

JDBC 负责三件事:

  1. 连接到数据源,如数据库
  2. 向数据库发送查询和更新语句
  3. 检索并处理从数据库接收到的结果

JDBC 具体编程步骤:

  1. 引入驱动并加载
  2. 建立数据库连接
  3. 创建语句对象
  4. 执行SQL语句并返回结果
  5. 处理结果
  6. 关闭资源

只是看是学不会的,要赋予实际的行动——敲代码!


http://www.niftyadmin.cn/n/4950980.html

相关文章

无涯教程-Perl - unshift函数

描述 此函数按顺序将LIST中的元素放在ARRAY的开头。这与shift()相反。 语法 以下是此函数的简单语法- unshift ARRAY, LIST返回值 此函数返回ARRAY中新元素的数量。 例 以下是显示其基本用法的示例代码- #!/usr/bin/perl -warray ( 1, 2, 3, 4);print "Value of a…

“深入剖析JVM内部工作原理:解密Java虚拟机“

标题:深入剖析JVM内部工作原理:解密Java虚拟机 摘要: 本文将深入剖析Java虚拟机(JVM)的内部工作原理,包括类加载、运行时数据区、垃圾回收、即时编译等关键概念和机制。通过对JVM的解密,我们将…

工具推荐:Chat2DB一款开源免费的多数据库客户端工具

文章首发地址 Chat2DB是一款开源免费的多数据库客户端工具,适用于Windows和Mac操作系统,可在本地安装使用,也可以部署到服务器端并通过Web页面进行访问。 相较于传统的数据库客户端软件如Navicat、DBeaver,Chat2DB具备了与AIGC…

慎用!澳洲留学生用ChatGPT写论文被控学术不端!AI论文漏洞百出,各高校已加强捡测!

自从进入ChatGPT时代以来,留学生们纷纷表示写作业,so easy。留学生们在用AI写论文时候没有预计到的是,ChatGPT存在杜撰文献的问题,并且学校已经在使用AI检测工具。 目前全澳大多数大学都可以选择使用现在很流行的反剽窃软件服务T…

自动编码器中的马尔可夫链蒙特卡罗期望最大化 (MCMC-EM):使用贝叶斯推理增强学习

一、介绍 自动编码器 自动编码器是强大的无监督学习算法,用于表示学习和降维。它们的工作原理是将输入数据编码为低维表示形式,然后将其解码回以重建原始数据。训练自动编码器通常涉及优化参数以最小化重建误差。然而,传统的优化技术&#xf…

阿里云容器镜像服务ACR(Alibaba Cloud Container Registry)推送镜像全过程及总结

前提:安装配置好docker,可参考我这篇 基于CentOS7安装配置docker与docker-compose。 一、设置访问凭证 1.1 容器镜像服务ACR 登录进入阿里云首页,点击 产品-容器-容器镜像服务ACR 点击管理控制台 1.2 进入控制台-点击实例列表 个人容器…

Java寻找数组的中心下标

目录 1.题目描述 2.题解 分析 具体实现 1.题目描述 给你一个整数数组 nums ,请计算数组的 中心下标 。 数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。 如果中心下标位于数组最左端,那么左侧数之和…

算法与数据结构(七)--堆

一.堆 1.堆的定义 堆是计算机科学中一类特殊的数据结构的通常,堆通常可以被看做是一颗完全二叉树的数组对象。 堆的特性 1.它是完全二叉树,除了树的最后一层结点不需要是满的,其他的每一层从左到右都是满的,如果最后一层结点不…