第10章 JDBC

10.1 什么是JDBC

JDBC的全称是Java数据库连接(Java Database Connectivity),它是一套用于执行SQL语句的Java API。应用程序可通过这套API连接到关系型数据库,并使用SQL语句完成对数据库中数据的新增、删除、修改和查询等操作。

不同的数据库(如MySQL、Oracle等)在内部处理数据的方式是不同的,如果直接使用数据库厂商提供的访问接口操作数据库,应用程序的可移植性就会变得很差。例如,用户在当前程序中使用的是MySQL提供的接口操作数据库,如果换成Oracle数据库,则需要重新使用Oracle数据库提供的接口,这样代码的改动量会非常大。有了JDBC后,这种情况就不复存在了,因为它要求各个数据库厂商按照统一的规范提供数据库驱动,在程序中由JDBC和具体的数据库驱动联系,因此用户就不必直接与底层的数据库交互,使得代码的通用性更强。

应用程序使用JDBC访问数据库的方式如下图。

10.2 JDBC常用API

在开发JDBC程序前,先了解一下JDBC常用的API。JDBC API主要位于java.sql包中,该包定义了一系列访问数据库的接口和类。

(1)Driver接口

Driver接口是所有JDBC驱动程序必须实现的接口,该接口专门提供给数据库厂商使用。需要注意的是,在编写JDBC程序时,必须要把所使用的数据库驱动程序或类库加载到项目的classpath中(这里指MySQL驱动JAR包)。

(2)DriverManager接口

DriverManager接口用于加载JDBC驱动、创建与数据库的连接。在DriverManager接口中,定义了两个比较重要的静态方法

方法名称功能描述
static void registerDriver(Driver driver)用于向DriverManager注册给定的JDBC驱动程序
static Connection getConnection (String url,String user,String pwd)用于建立和数据库的连接,并返回表示连接的Connection对象

(3)Connection接口

Connection接口用于处理与特定数据库的连接,Connection对象是表示数据库连接的对象,只有获得该连接对象,才能访问并操作数据库。Connection接口的常用方法如下表。

方法名称功能描述
Statement createStatement()用于创建一个Statement对象将SQL语句发送到数据库
PreparedStatement prepareStatement(String sql)用于创建一个PreparedStatement对象将参数化的SQL语句发送到数据库
CallableStatement prepareCall(String sql)用于创建一个CallableStatement对象来调用数据库存储过程

(4)Statement接口

Statement接口用于执行静态的SQL语句,并返回一个结果对象。Statement接口对象可以通过Connection实例的createStatement()方法获得,该对象会把静态的SQL语句发送到数据库中编译执行,然后返回数据库的处理结果。

Statement接口提供了3个常用的执行SQL语句的方法。

方法名称功能描述
boolean execute(String sql)用于执行各种SQL语句。该方法返回一个boolean类型的值,如果为true,表示所执行的SQL语句有查询结果,可以通过Statement的getResultSet()方法获得查询结果。
int executeUpdate(String sql)用于执行SQL中的insert、update和delete语句。该方法返回一个int类型的值,表示数据库中受该SQL语句影响的记录条数。
ResultSet executeQuery(String sql)用于执行SQL中的select语句。该方法返回一个表示查询结果的ResultSet对象。

(5)PreparedStatement 接口

Statement接口封装了JDBC执行SQL语句的方法,可以完成Java程序执行SQL语句的操作。然而在实际开发过程中往往需要将程序中的变量作为SQL语句的查询条件,而使用Statement接口操作这些SQL语句会过于繁琐,并且存在安全方面的问题。针对这一问题,JDBC API 提供了扩展的PreparedStatement接口。

PreparedStatement是Statement的子接口,用于执行预编译的SQL语句。PreparedStatement接口扩展了带有参数SQL语句的执行操作,该接口中的SQL语句可以使用占位符“?”代替参数,然后通过setter()方法为SQL语句的参数赋值。

PreparedStatement接口提供了一些常用方法,如下表。

方法名称功能描述
int executeUpdate()在PreparedStatement对象中执行 SQL 语句,SQL语句必须是一个DML语句或者是无返回内容的SQL 语句,如 DDL 语句。
ResultSet executeQuery()在PreparedStatement对象中执行 SQL 查询,该方法返回的是ResultSet对象。
void setInt(int parameterIndex, int x)将指定参数设置成给定的int值。
void setString(int parameterIndex,String x)将指定参数设置成给定的String值。

通过setter()方法为SQL语句中的参数赋值时,可以通过已定义的SQL类型参数兼容输入参数。例如,如果参数具有的SQL类型为Integer,那么应该使用setInt()方法或setObject()方法设置多种类型的输入参数,具体示例如下所示:

String sql = "INSERT INTO users(id,name,email) VALUES(?,?,?)";
PreparedStatement preStmt = conn.prepareStatement(sql);
preStmt.setInt(1, 1); //使用参数的已定义SQL类型
preStmt.setString(2, "zhangsan"); //使用参数的已定义SQL类型
preStmt.setObject(3, "zs@sina.com"); //使用setObject()方法设置参数
preStmt.executeUpdate();

(6)ResultSet接口

ResultSet接口用于保存JDBC执行查询时返回的结果集,该结果集封装在一个逻辑表格中。在ResultSet接口内部有一个指向表格数据行的游标(或指针),ResultSet对象初始化时,游标在表格的第一行之前,调用next()方法可以将游标移动到下一行。如果下一行没有数据,则返回false。在应用程序中经常使用next()方法作为while循环的条件来迭代ResultSet结果集。

ResultSet接口的常用方法如下表。

方法名称功能描述
String getString(int columnIndex)用于获取指定字段的String类型的值,参数columnIndex代表字段的索引。
String getString (String columnName)用于获取指定字段的String类型的值,参数columnName代表字段的名称。
int getInt(int columnIndex)用于获取指定字段的int类型的值,参数columnIndex代表字段的索引。
int getInt(String columnName)用于获取指定字段的int类型的值,参数columnName代表字段的名称。
boolean next()将游标从当前位置向下移一行。

从上个表格中可以看出,ResultSet接口中定义了一些getter方法,而采用哪种getter方法获取数据取决于字段的数据类型。程序既可以通过字段的名称来获取指定数据,也可以通过字段的索引来获取指定的数据,字段的索引是从1开始编号的。例如,数据表的第一列字段名为id,字段类型为int,那么既可以使用getInt(1)获取该列的值,也可以使用getInt(“id”)获取该列的值。

10.3 实现第一个JDBC程序

使用JDBC的常用API实现JDBC程序的步骤如下图。

接下来分步骤讲解使用JDBC的API连接数据库的过程。

(1)加载并注册数据库驱动

在连接数据库之前,要加载数据库的驱动到JVM(Java虚拟机)。加载操作可以通过java.lang.Class类的静态方法forName(String className)或DriverManager类的静态方法registerDriver(Driver driver)实现,具体示例如下所示:

DriverManager.registerDriver(Driver driver);

Class.forName("DriverName");

在实际开发中,我们常用第2种方式注册数据库驱动,DriverName表示数据库的驱动类。以MySQL数据库为例,MySQL驱动类在6.0.2版本之前为com.mysql.jdbc.Driver,而在6.0.2版本之后为com.mysql.cj.jdbc.Driver,我们要根据自己数据库版本选择对应的驱动类。

(2)通过DriverManager获取数据库连接

获取数据库连接的具体方式如下:

Connection conn = DriverManager.getConnection(String url, String user, String pwd); 

从上述代码可以看出,getConnection()方法有3个参数,分别表示连接数据库的地址、登录数据库的用户名和密码。以MySQL数据库为例,MySQL数据库地址的书写格式如下:

jdbc:mysql://hostname:port/databasename

在上面代码中,jdbc:mysql:是固定的写法,mysql指的是MySQL数据库,hostname指的是主机的名称(如果数据库在本机中,hostname可以为localhost或127.0.0.1;如果要连接的数据库在其他电脑上,hostname为所要连接电脑的IP),port指的是连接数据库的端口号(MySQL端口号默认为3306),databasename指的是MySQL中相应数据库的名称。

通过Connection对象获取Statement对象

Connection创建Statement对象的方法有以下3个:

● createStatement():创建基本的Statement对象。

● prepareStatement():创建PreparedStatement对象。

● prepareCall():创建CallableStatement对象。

以创建基本的Statement对象为例,创建方式如下:

Statement stmt = conn.createStatement();

(4)使用Statement执行SQL语句

所有的Statement都有以下3种执行SQL语句的方法:

● execute():可以执行任何SQL语句。

● executeQuery():通常执行查询语句,执行后返回代表结果集的ResultSet对象。

● executeUpdate():主要用于执行DML和DDL语句。执行DML语句,如INSERT、UPDATE或DELETE时,返回受SQL语句影响的行数;执行DDL语句返回0。

以executeQuery()方法为例,executeQuery()方法调用形式如下:

// 执行SQL语句,获取结果集ResultSet

ResultSet rs = stmt.executeQuery(sql);

(5)操作ResultSet结果集

如果执行的SQL语句是查询语句,执行结果将返回一个ResultSet对象,该对象保存了SQL语句查询的结果。程序可以通过操作该ResultSet对象取出查询结果。

(6)关闭连接,释放资源

每次操作数据库结束后都要关闭数据库连接,释放资源,关闭顺序和声明顺序相反。需要关闭的资源包括ResultSet、Statement和Connection等。

接下来,依照上面所讲解的步骤编写Java程序演示JDBC的使用,该程序从users表中读取数据,并将结果打印在控制台,具体步骤如下所示。

(1)搭建数据库环境

在MySQL中创建一个名称为jdbc的数据库,然后在jdbc数据库中创建一个users表,创建数据库和表的SQL语句如下所示:

CREATE DATABASE jdbc;
USE jdbc;
CREATE TABLE users(
		id INT PRIMARY KEY AUTO_INCREMENT,
		name VARCHAR(40),
		password VARCHAR(40),
		email VARCHAR(60),
		birthday DATE 
);

jdbc数据库和users表创建成功后,再向users表中插入3条数据,插入的SQL语句如下所示:

INSERT INTO users(NAME,PASSWORD,email,birthday) 
VALUES('zhangs','123456','zs@sina.com','1980-12-04'),
('lisi','123456','lisi@sina.com','1981-12-04'),
('wangwu','123456','wangwu@sina.com','1979-12-04');

为了查看数据是否添加成功,使用SELECT语句查询users表中的数据,执行结果如下图。

(2)创建项目环境,导入数据库驱动

在IDEA中新建一个名称为chapter10的Java项目,使用鼠标右键单击项目名称,选择【New】→【Directory】,在弹出窗口中将该文件夹命名为lib,项目根目录中就会出现一个名称为lib的文件夹。

将下载好的MySQL数据库驱动文件mysql-connector-java-8.0.1.jar复制到项目的lib目录中,并把jar包添加到项目里。使用鼠标单击File菜单栏,选择【Project Structure】→【Modules】→【Dependencies】,单击最右侧加号后选择第一项:JARs or directories…,在弹出框中选择下载好的Jar包确认。

最后可以看到mysql-connector-java-8.0.1.jar包添加到IDEA的依赖项中,添加成功界面如右图。

在上图中,mysql-connector-java-8.0.1.jar包添加到依赖项之后,单击【Apply】后再单击【OK】,可以看到在External libraries下已经存在刚刚添加的jar包。至此,jar包添加成功。加入数据库驱动后的项目结构如下图。

(3)编写JDBC程序

在项目chapter10的src目录下,新建一个名称为cn.itcast.jdbc.example的包,在该包中创建类Example01,Example01类用于读取数据库中的users表,并将结果输出到控制台。

import java.sql.*;
public class Example01 {
    public static void main(String[] args) throws SQLException {
        Statement stmt = null;
        ResultSet rs = null;
        Connection conn = null;
        try {
            // 1. 注册数据库的驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 2.通过DriverManager获取数据库连接
            String url = 
            "jdbc:mysql://localhost:3306/jdbc
            ?serverTimezone=GMT%2B8&useSSL=false";
            String username = "root";
            String password = "root";
            conn = DriverManager.getConnection(url, username, password);
            // 3.通过Connection对象获取Statement对象
            stmt = conn.createStatement();
            // 4.使用Statement执行SQL语句。
            String sql = "select * from users";
            rs = stmt.executeQuery(sql);
            // 5. 操作ResultSet结果集
            System.out.println("id	|	name	|	password"
                    + "|	email		|	birthday");
            while (rs.next()) {
                int id = rs.getInt("id"); // 通过列名获取指定字段的值
                String name = rs.getString("name");
                String psw = rs.getString("password");
                String email = rs.getString("email");
                Date birthday = rs.getDate("birthday");
                System.out.println(id + "	|	" + name + "	|	" + psw +
                        "	|	" + email + "	|	" + birthday);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            // 6.回收数据库资源
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                rs = null;
            }
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                stmt = null;
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                conn = null;
            }
        }
    }
}

在上述代码中,在第9行代码中通过Class的forName()方法注册了MySQL数据库驱动;在第11~16行代码中通过DriverManager的getConnection()方法获取数据库的连接;第18行代码中通过Connection对象获取Statement对象,第20~21行代码使用Statement的executeQuery()方法执行SQL查询语句;第23~33行代码使用ResultSet操作结果集,并用while循环获取所有数据库数据,第38~62行代码使用close()方法将Statement、ResultSet和Connection都关闭并置空。

在实现第一个JDBC程序时,还有以下3点需要注意:

1、注册驱动

虽然使用DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver())方法也可以完成注册,但这种方式会使数据库驱动被注册两次。因为在Driver类的源码中,已经在静态代码块中完成了数据库驱动的注册。为了避免数据库驱动被重复注册,只需要在程序中使用Class.forName()方法加载驱动类即可。

2、释放资源

由于数据库资源非常宝贵,数据库允许的并发访问连接数量有限,因此,当数据库资源使用完毕后,一定要记得释放资源。为了保证资源的释放,在Java程序中,应该将释放资源的操作放在finally代码块中。

3、获取数据库连接

在新版本中获取数据库连接时需要设置时区为北京时间(serverTimezone=GMT%2B8),因为安装数据库时默认为美国时间。如果不设置时区为北京时间,系统会报MySQL设置时区与当前电脑系统时区不符的错误,如下图。

此外,MySQL高版本需要指明是否进行SSL连接,否则会出现警告信息。警告信息具体如下所示:

Fri Mar 20 18:55:47 CST 2020 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.

遇到这种情况,只需要在mysql连接字符串url中加入useSSL=true或者false即可,具体示例如下所示。

url=jdbc:mysql://127.0.0.1:3306/jdbc?characterEncoding=utf8&useSSL=true

10.4 本章小结

本章主要讲解了JDBC的基本知识,包括什么是JDBC、JDBC的常用API、JDBC的使用,以及如何在项目中使用JDBC实现对数据的增删改查等知识。通过本章的学习,读者可以了解到什么是JDBC,熟悉JDBC的常用API,掌握如何使用JDBC操作数据库等。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Trie 字典树的两种实现方式

Trie,又称字典树、单词查找树或键树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是…

github Two-factor authentication (2FA)is required for your GitHub account

问题 github 2FA认证 详细问题 笔者使用GitKraken,使用github登录,github要去 Two-factor authentication (2FA)is required for your GitHub account,即进行2FA认证 解决方案 解决方案一、 微信 → \rightarrow →搜索腾讯身份验证器…

内存块与内存池

(1)在运行过程中,MemoryPool内存池可能会有多个用来满足内存申请请求的内存块,这些内存块是从进程堆中开辟的一个较大的连续内存区域,它由一个MemoryBlock结构体和多个可供分配的内存单元组成,所有内存块组…

java 培训班预定管理系统Myeclipse开发mysql数据库web结构jsp编程servlet计算机网页项目

一、源码特点 java 培训班预定管理系统是一套完善的java web信息管理系统 采用serlvetdaobean,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xf…

java 宠物医院系统Myeclipse开发mysql数据库web结构jsp编程计算机网页项目

一、源码特点 java 宠物医院系统是一套完善的java web信息管理系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql5.0&…

Excel如何把窗口冻结,在下拉滚动条的时候仍然可以看到前几行数据?

** 共分2个情况: ①: 冻结首行: 作用:只冻结第一行的数据窗口。在下拉滚动条时,首行不会动,其他数据行会动步骤如下:1、鼠标放在首行的最左边,然后左键点一下先选中整行2、然后&am…

OpenAI发布Sora技术报告深度解读!真的太强了!

😎 作者介绍:我是程序员洲洲,一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主、前后端开发、人工智能研究生。公粽号:洲与AI。 🎈 本文专栏:本文收录…

IP地址+子网掩码+CIDR学习笔记

目录 一、IP地址 1、表示方法: 2、特殊IP地址 二、子网掩码 1、判断网络位和主机位 2、子网划分 三、无分类编址CIDR 1、CIDR路由汇聚 汇聚规则: 汇聚ID: 2、最佳路由匹配原则 一、IP地址 1、表示方法: 机器中存放的…

UE Get节点和源码

文章目录 概要UE Get节点有哪些常见的应用场景相关源码 概要 UE Get节点在Unreal Engine的蓝图系统中用于获取变量的值。这个节点通常用于从变量中读取数据,以便在游戏的逻辑流程中使用。 要使用Get节点,你首先需要有一个已经定义的变量。然后&#xf…

电梯控制系列之电梯结构介绍

这篇博客介绍单部10层电梯的完整控制程序框架编写过程,编程语言:SCL,控制器型号:S7-1200PLC。本篇博客介绍和电梯控制相关的一些电梯结构介绍。本文只可作为学习参考资料,行业控制需要遵循电梯安全相关规范。 1、电梯…

【Linux系统化学习】缓冲区

目录 缓冲区 一个样例 现象解释 缓冲区存在的位置 缓冲区 在刚开始学习C语言的时候我们就听过缓冲区这个名词,很是晦涩难懂;在Linux下进程退出时也包含缓冲区,因此缓冲区到底是什么?有什么作用? 让我们先从一个小…

微服务—DSL基础语法与RestClient操作

本博客为个人学习笔记,学习网站:黑马程序员SpringCloud 2021教程 目录 DSL语法 索引库操作 mapping属性 创建索引库 字段拷贝 查询、删除、修改索引库 文档操作 新增文档 查询、删除文档 修改文档 全量修改 增量修改 DSL文档语法小结 Rest…

JWT登录验证前后端设计与实现笔记

设计内容 前端 配置全局前置路由守卫axios拦截器登录页面和主页 后端 JWT的封装登录接口中间件放行mysql数据库的连接 详细设计 路由设计 配置全局前置守卫,如果访问的是登录页面则放行,不是则进入判断是否有token,没有则拦截回到登录…

17-k8s控制器资源-job控制

job控制器:就是一次性任务的pod控制器,pod完成作业后不会重启,其重启策略是:Never 1,job控制器案例描述 启动一个pod,执行完成一个事件,然后pod关闭; 事件:计算π的值&a…

[java基础揉碎]类与对象

目录 类与对象的引出: 类与对象的概述: 类与对象在内存中的布局: 属性的注意细节: 类与对象在内存中创建的过程: 类与对象的引出: 例如这样一个问题: 如果用单独变量来解决, 就会有一个问题, 不利于数据的管理, 将所有猫的信息都给拆解了: 如果用数组来解决, 则会有 1)数…

第三百五十回

文章目录 1. 概要介绍2. 获取方法2.1 获取语言2.2 获取地址 3.示例代码3. 内容总结 我们在上一章回中介绍了"给geolocator插件提交问题"相关的内容,本章回中将介绍如何获取系统语言.闲话休提,让我们一起Talk Flutter吧。 1. 概要介绍 我们在本…

书生浦语-模型微调

大语言模型微调 指令微调的流程 LoRA(旁路分支微调) Xtuner微调框架 微调训练 作业 微调作业需要多训练几个epoch,这里训练了16个epoch

141 . 环形链表

链接 https://leetcode.cn/problems/linked-list-cycle/description/?envTypestudy-plan-v2&envIdtop-interview-150 题面 思路 : 法1 : 用哈希表来存之前的遍历过的结点 ; 一遍遍历,在遍历的过程中,先判断是否当前结点在哈希表…

【Redis实战】有MQ为啥不用?用Redis作消息队列!?Redis作消息队列使用方法及底层原理高级进阶

🎉🎉欢迎光临🎉🎉 🏅我是苏泽,一位对技术充满热情的探索者和分享者。🚀🚀 🌟特别推荐给大家我的最新专栏《Redis实战与进阶》 本专栏纯属为爱发电永久免费!&a…

IDEA配置Lombok不起作用

IDEA配置Lombok不起作用 我们通常会只用lombok来简化代码。但是使用IDEA的lombok插件时,Lombok并不起作用。 可以按照如下操作。 FIle -> settings ->build,excecution,deployment–>compiler–>annotation processors勾选上 enable annotation proc…