第十四讲 JDBC数据库

1. 什么是JDBC

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

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

图1 应用程序通过JDBC访问数据库方式

2. JDBC常用API

1Driver接口

Driver接口是所有JDBC驱动程序必须实现的接口,该接口专门提供给数据库厂商使用。

注意:在编写JDBC程序时,必须要把所使用的数据库驱动程序或类库加载到项目的classpath中(这里指数据库的驱动JAR包)。

(2)DriverManager类

DriverManager类用于加载JDBC驱动并且创建与数据库的连接。其主要方法如表1所示。

表1 DriverManager类常用方法

方法声明

功能描述

static synchronized void registerDriver(Driver driver)

该方法用于向DriverManager中注册给定的JDBC驱动程序

static Connection getConnection(String url,String user,String pwd)

该方法用于建立和数据库的连接,并返回表示连接的Connection对象

说明:在实际开发中,通常不使用registerDriver(Driverdriver)注册驱动。因为JDBC驱动类Driver中有一段静态代码块,是向DriverManager注册一个Driver实例,当再次执行registerDriver(newDriver()),相当于实例化了两个Driver对象,因此在加载数据库驱动时通常使用Class类的静态方法forName()来实现。

(3) Connection接口

Connection接口代表Java程序和数据库的连接对象,只有获得该连接对象后,才能访问数据库,并操作数据表。Connection接口常用方法如表2所示。

表2 Connection接口

方法声明

功能描述

Statement createStatement()

该方法用于返回一个向数据库发送语句的Statement对象

PreparedStatement prepareStatement(String sql)

该方法用于返回一个PreparedStatement对象,该对象用于向数据库发送参数化的SQL语句

CallableStatement prepareCall(String sql)

该方法用于返回一个CallableStatement对象,该对象用于调用数据库中的存储过程

(4) Statement接口

Statement是Java执行数据库操作的一个重要接口,它用于执行静态的SQL语句,并返回一个结果对象。

说明:Statement接口对象可以通过Connection实例的createStatement()方法获得,然后返回数据库的处理结果。Statement接口常用方法如表3所示。

表3 Statement常用方法

方法声明

功能描述

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语句可以使用占位符“?”来代替其参数,然后通过setXxx()方法为SQL语句的参数赋值。

PreparedStatement接口常用方法如表4所示。

表4 PreparedStatement接口常用方法

方法声明

功能描述

int executeUpdate()

在此PreparedStatement对象中执行 SQL 语句,该语句必须是一个DML语句或者是无返回内容的SQL 语句,如 DDL 语句

ResultSet executeQuery()

在此PreparedStatement对象中执行 SQL 查询,该方法返回的是ResultSet对象

void setInt(int parameterIndex, int x)

将指定参数设置为给定的int值

void setFloat(int parameterIndex, float x)

将指定参数设置为给定的float值

void setString(int parameterIndex, String x)

将指定参数设置为给定的String值

void setDate(int parameterIndex, Date x)

将指定参数设置为给定的Date值

void addBatch()

将一组参数添加到此PreparedStatement对象的批处理命令中

void setCharacterStream(int parameterIndex,  java.io.Reader reader,  int length)

将指定的输入流写入数据库的文本字段

void setBinaryStream(int parameterIndex, java.io.InputStream x, int length)

将二进制的输入流数据写入到二进制字段中

为SQL语句参数赋值时,可以通过输入参数与SQL类型相匹配的setXxx()方法。例如字段的数据类型为int或Integer,那么应该使用setInt()方法,也可以通过setObject()方法设置多种类型的输入参数。

    // 假设users表中字段id、name、email类型分别是int、varchar、varchar

    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接口常用方法如表5所示。

表5 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代表字段的名称

Date getDate(int columnIndex)

用于获取指定字段的Date类型的值,参数columnIndex代表字段的索引

Date getDate(String

 columnName)

用于获取指定字段的Date类型的值,参数columnName代表字段的名称

boolean next()

将游标从当前位置向下移一行

boolean absolute(int row)

将游标移动到此 ResultSet 对象的指定行

void afterLast()

将游标移动到此 ResultSet 对象的末尾,即最后一行之后

void beforeFirst()

将游标移动到此 ResultSet 对象的开头,即第一行之前

boolean previous()

将游标移动到此 ResultSet 对象的上一行

boolean last()

将游标移动到此 ResultSet 对象的最后一行

ResultSet接口中定义了大量的getXxx()方法,而采用哪种getXxx()方法取决于字段的数据类型。

程序既可以通过字段的名称来获取指定数据,也可以通过字段的索引来获取指定的数据,字段的索引是从1开始编号的。

例如,假设数据表的第1列字段名为id,字段类型为int,那么既可以使用getInt("id")获取该列的值,也可以使用getInt(1)获取该列的值。

3. JDBC编程的基本步骤

通常情况下,JDBC编程可分为如下几个基本步骤。

(1)加载数据库驱动

 加载数据库驱动通常使用Class类的静态方法forName()来实现,使用格式:

Class.forName(DriverName);

上述代码中,DriverName代表的是数据库驱动类所对应的字符串。例如,要加载MySQL数据库的驱动可以采用如下代码。

Class.forName("com.mysql.jdbc.Driver");

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

DriverManager提供了一个getConnection()方法来获取数据库连接,使用格式如下。

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

   参数说明:

url:表示连接数据库的URL。

user:表示登录数据库的用户名。

pwd:表示登录数据库的密码。

用户名和密码通常由数据库管理员设置,而连接数据库的URL则有固定格式。如MySQL数据库的URL地址为。

jdbc:mysql://hostname:prot/databasename

上述代码中,jdbc:mysql:是固定写法,mysql指的是MySQL数据库;hostname指的是MySQL数据库所在的主机名或IP地址(例如数据库在本机上,hostname可以是localhost或127.0.0.1);port指的是连接数据库的端口号(默认为3306);databasename指的是要操作的数据库。

(3)通过Connection对象获取Statement对象

Connection创建Statement的方式有3种。

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

②prepareStatement(String sql):根据传递的SQL语句创建PreparedStatement对象。

③prepareCall(Stringsql):根据传入的SQL语句创建CallableStatement对象。

例创建基本的Statement对象,其代码如下所示。

Statement stmt = conn.createStatement();

(4)使用Statement执行SQL语句

可通过如下3种不同的方式来执行SQL语句。

①execute(String sql):用于执行任意的SQL语句。

②executeQuery(String sql):用于执行查询语句,返回ResultSet结果集对象。

③executeUpdate(String sql):主要用于执行DML(数据操作语言)和DDL(数据定义语言)语句。执行DML语句(INSERT、UPDATE或DELETE)时,会返回受SQL语句影响的行数,执行DDL(CREATE、ALTER)语句返回0。

例执行查询SQL,获取结果集:

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

ResultSet rs = stmt.executeQuery(sql);

(5)操作ResultSet结果集

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

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

每次操作数据库结束后都要关闭数据库连接,释放资源,以重复利用资源。通常资源的关闭顺序与打开顺序相反,顺序是ResultSet、Statement(或PreparedStatement)和Connection。为了保证在异常情况下也能关闭资源,需要在try...catch的finally代码块中统一关闭资源。

4. JDBC编程示例

(1)添加mysql驱动

①在项目中新建一lib目录,将mysql的驱动程序复制到此目录中。

②选择菜单【file】-【project structure】,左侧选择“modules”,右侧中间选择“Dependencies”,然后点击右上角的“+”号,选择“1 jars or directories…”,如下图所示。

③在弹出的对话框中选择项目中lib目录下的mysql驱动,然后点击”ok”返回。

④此时在Dependencies中会多了刚才选中的mysql驱动,然后点击“ok”即可。

(2)数据库操作

假设要操作的MySQL数据库名为db_student,db_student数据库中有一个表为tb_stud,表中内容如下所示。

【例10-1】读取表中内容并显示

import java.sql.*;


public class JDBCShow {

    public static void main(String[] args) throws SQLException {

        Connection conn = null;

        Statement stmt = null;

        ResultSet rs = null;

        try{

            Class.forName("com.mysql.jdbc.Driver");

            String url = "jdbc:mysql://localhost:3306/db_student?characterEncoding=utf8";

            String username="root";

            String password = "";

            conn = DriverManager.getConnection(url,username,password);

            stmt = conn.createStatement();

            rs = stmt.executeQuery("select * from tb_stud");

            System.out.println("no\t\tname\tmath\tchinese\tenglish");

            while(rs.next()){

                String no = rs.getString("no");

                String name = rs.getString("name");

                int math = rs.getInt("math");

                int chinese = rs.getInt("chinese");

                int english = rs.getInt("english");

                System.out.println(no + "\t" +name + "\t" + math + "\t\t" + chinese+"\t\t"+ english);

            }

        }catch(Exception e){

            e.printStackTrace();

        }finally{

            if(rs!=null) {

                rs.close();

            }

            if(stmt!=null){

                stmt.close();

            }

            if (conn!=null){

                conn.close();

            }

        }

    }

}

运行结果如下图所示。

【例10-2】先往表中插入记录,然后读取表中记录显示

import java.sql.*;


public class JDBCInsertShow {

    public static void main(String[] args) throws SQLException {

        Connection conn = null;

        Statement stmt = null;

        ResultSet rs = null;

        try{

            Class.forName("com.mysql.jdbc.Driver");

            String url = "jdbc:mysql://localhost:3306/db_student?characterEncoding=utf8";

            String username="root";

            String password = "";

            conn = DriverManager.getConnection(url,username,password);

            stmt = conn.createStatement();

            String sql = "insert into tb_stud(no,name,math,chinese,english) values(?,?,?,?,?)";

            PreparedStatement preStmt =conn.prepareStatement(sql);

            preStmt.setString(1,"1005");

            preStmt.setString(2,"张小");

            preStmt.setInt(3,80);

            preStmt.setInt(4,99);

            preStmt.setInt(5,90);

            preStmt.executeUpdate();

            rs = stmt.executeQuery("select * from tb_stud");

            System.out.println("no\t\tname\tmath\tchinese\tenglish");

            while(rs.next()){

                String no = rs.getString("no");

                String name = rs.getString("name");

                int math = rs.getInt("math");

                int chinese = rs.getInt("chinese");

                int english = rs.getInt("english");

                System.out.println(no + "\t" +name + "\t" + math + "\t\t" + chinese+"\t\t"+ english);

            }

        }catch(Exception e){

            e.printStackTrace();

        }finally{

            if(rs!=null) {

                rs.close();

            }

            if(stmt!=null){

                stmt.close();

            }

            if (conn!=null){

                conn.close();

            }

        }

    }

}

运行结果如下图所示。

此时数据库表中内容如下所示。

【例10-3】记录的增、删、改、显示操作

import java.sql.*;


public class JDBCOperator {

    public static void main(String[] args) throws SQLException {

        Connection conn = null;

        Statement stmt = null;

        ResultSet rs = null;

        try{

            Class.forName("com.mysql.jdbc.Driver");

            String url = "jdbc:mysql://localhost:3306/db_student?characterEncoding=utf8";

            String username = "root";

            String pw = "";

            conn = DriverManager.getConnection(url,username,pw);

            stmt = conn.createStatement();

            String sql = "update tb_stud set name='王明' where id=1";   //记录的修改

            stmt.executeUpdate(sql);

            sql = "insert into tb_stud values(null,'1004','张朋',70,70,70)"; //记录的添加

            stmt.executeUpdate(sql);

            sql = "delete from tb_stud where name='李军'";   //记录的删除

            stmt.executeUpdate(sql);

            rs = stmt.executeQuery("select * from tb_stud");

            System.out.println("no\t\tname\tmath\tchinese\tenglish");

            while(rs.next()){

                String no = rs.getString("no");

                String name = rs.getString("name");

                int math = rs.getInt("math");

                int chinese = rs.getInt("chinese");

                int english = rs.getInt("english");

                System.out.println(no + "\t" +name + "\t" + math + "\t\t" + chinese+"\t\t"+ english);

            }

        }catch(Exception e){

            e.printStackTrace();

}        }finally{

            if (rs!=null){

                rs.close();

            }

            if (stmt!=null) {

                stmt.close();

            }

            if (conn!=null) {

                conn.close();

            }

        }

    }

运行结果如下图所示。

此时表中内容如下所示。

 

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

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

相关文章

JVM面试题解,垃圾回收之“分代回收理论”剖析

一、什么是分代回收 我们会把堆内存中的对象间隔一段时间做一次GC(即垃圾回收),但是堆内存很大一块,内存布局分为新生代和老年代、其对象的特点不一样,所以回收的策略也应该各不相同 对于“刚出生”的新对象&#xf…

电脑如何访问手机文件?

手机和电脑已经深深融入了我们的日常生活,无时无刻不在为我们提供服务。除了电脑远程操控电脑外,我们还可以在电脑上轻松地访问Android或iPhone手机上的文件。那么,如何使用电脑远程访问手机上的文件呢? 如何使用电脑访问手机文件…

ThinkPHP 8模型与数据的插入、更新、删除

【图书介绍】《ThinkPHP 8高效构建Web应用》-CSDN博客 《2025新书 ThinkPHP 8高效构建Web应用 编程与应用开发丛书 夏磊 清华大学出版社教材书籍 9787302678236 ThinkPHP 8高效构建Web应用》【摘要 书评 试读】- 京东图书 使用VS Code开发ThinkPHP项目-CSDN博客 编程与应用开…

【MySQL】数据库基础知识

欢迎拜访:雾里看山-CSDN博客 本篇主题:【MySQL】数据库基础知识 发布时间:2025.1.21 隶属专栏:MySQL 目录 什么是数据库为什么要有数据库数据库的概念 主流数据库mysql的安装mysql登录使用一下mysql显示数据库内容创建一个数据库创…

【线性代数】基础版本的高斯消元法

[精确算法] 高斯消元法求线性方程组 线性方程组 考虑线性方程组, 已知 A ∈ R n , n , b ∈ R n A\in \mathbb{R}^{n,n},b\in \mathbb{R}^n A∈Rn,n,b∈Rn, 求未知 x ∈ R n x\in \mathbb{R}^n x∈Rn A 1 , 1 x 1 A 1 , 2 x 2 ⋯ A 1 , n x n b 1…

高等数学学习笔记 ☞ 微分方程

1. 微分方程的基本概念 1. 微分方程的基本概念: (1)微分方程:含有未知函数及其导数或微分的方程。 举例说明微分方程:;。 (2)微分方程的阶:指微分方程中未知函数的导数…

HarmonyOS基于ArkTS卡片服务

卡片服务 前言 Form Kit(卡片开发框架)提供了一种在桌面、锁屏等系统入口嵌入显示应用信息的开发框架和API,可以将应用内用户关注的重要信息或常用操作抽取到服务卡片(以下简称“卡片”)上,通过将卡片添加…

Java复习第四天

一、代码题 1.相同的树 (1)题目 给你两棵二叉树的根节点p和q,编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。 示例 1: 输入:p[1,2,3],q[1,2,3] 输出:true示例 2: 输…

全面了解 Web3 AIGC 和 AI Agent 的创新先锋 MelodAI

不管是在传统领域还是 Crypto,AI 都是公认的最有前景的赛道。随着数字内容需求的爆炸式增长和技术的快速迭代,Web3 AIGC(AI生成内容)和 AI Agent(人工智能代理)正成为两大关键赛道。 AIGC 通过 AI 技术生成…

新能源汽车充电桩选型以及安装应用

摘要:随着当前经济的不断发展,国家的科技也有了飞速的进步,传统的燃油汽车已经不能适应当前社会的发展,不仅对能源造成巨大的消耗,还对环境造成了污染,当前一种新型的交通运输工具正在占领汽车市场。在环境问题和能源问题愈发严重的当今社会,节能减排已经成为全世界的共同课题,…

一个vue项目npm install失败的问题解决方案

vue的项目一直是史上最难的最烦的问题,今天给别人做毕设单子想在gitee上拉项目二开的时候,由于很久没写过vue项目已经生疏了,在拿到项目之后我还是例行完成最常见的步骤: 1、npm init -y 初始化 2、npm install 用npm把这个项目…

计算机网络 (55)流失存储音频/视频

一、定义与特点 定义:流式存储音频/视频是指经过压缩并存储在服务器上的多媒体文件,客户端可以通过互联网边下载边播放这些文件,也称为音频/视频点播。 特点: 边下载边播放:用户无需等待整个文件下载完成即可开始播放…

UE求职Demo开发日志#6 测试用强化页面UI搭建

1 反向实现思路设计 先看最终效果: 先做了一个大致的分区,右侧的上半部分用来显示数据,下半部分用来强化和显示需要的材料,至于这个背景设定上强化应该叫什么,。。。。,还没定,反正应该不叫强…

python学opencv|读取图像(四十一 )使用cv2.add()函数实现各个像素点BGR叠加

【1】引言 前序已经学习了直接在画布上使用掩模,会获得彩色图像的多种叠加效果,相关文章链接为: python学opencv|读取图像(四十)掩模:三通道图像的局部覆盖-CSDN博客 这时候如果更进一步,直接…

SpringCloudAlibaba 服务保护 Sentinel 项目集成实践

目录 一、简介1.1、服务保护的基本概念1.1.1、服务限流/熔断1.1.2、服务降级1.1.3、服务的雪崩效应1.1.4、服务的隔离的机制 1.2、Sentinel的主要特性1.3、Sentinel整体架构1.4、Sentinel 与 Hystrix 对比 二、Sentinel控制台部署3.1、版本选择和适配3.2、本文使用各组件版本3.…

窥探QCC518x-308x系列与手机之间的蓝牙HCI记录与分析 - 耳机篇

上一篇是介绍如何窥探手机端Bluetooth的HCI log, 本次介绍是如何窥探Bluetooth的HCI log-耳机篇. 这次跟QCC518x/QCC308x测试的手机是Samsung S23 Ultra. QCC518x/QCC308x透过HCI界面取得Log教学. 步骤1: 开启QMDE -> 选择ADK r1102 QCC3083 Headset workspace.步骤2: 点…

C++ list 容器用法

C list 容器用法 C 标准库提供了丰富的功能&#xff0c;其中 <list> 是一个非常重要的容器类&#xff0c;用于存储元素集合&#xff0c;支持双向迭代器。<list> 是 C 标准模板库&#xff08;STL&#xff09;中的一个序列容器&#xff0c;它允许在容器的任意位置快速…

SpringSecurity实现自定义用户认证方案

Spring Security 实现自定义用户认证方案可以根据具体需求和业务场景进行设计和实施&#xff0c;满足不同的安全需求和业务需求。这种灵活性使得认证机制能够更好地适应各种复杂的环境和变化‌。通过自定义认证方案&#xff0c;可以更好地控制和管理用户的访问权限&#xff0c;…

深入内核讲明白Android Binder【三】

深入内核讲明白Android Binder【三】 前言一、服务的获取过程内核源码解析1. 客户端获取服务的用户态源码回顾2. 客户端获取服务的内核源码分析2.1 客户端向service_manager发送数据1. binder_ioctl2. binder_ioctl_write_read3. binder_thread_write4. binder_transaction4.1 …

深入解析:Docker 容器如何实现文件系统与资源的多维隔离?

目录 一、RootFs1. Docker 镜像与文件系统层2. RootFs 与容器隔离的意义 二、Linux Namespace1. 进程命名空间1.1 lsns 命令说明1.2 查看“祖先进程”命名空间1.3 查看当前用户进程命名空间 2. 容器进程命名空间2.1 查看容器进程命名空间列表2.2 容器进程命名空间的具体体现 三…