JDBC介绍

article/2025/8/24 7:53:36

1 JDBC简介

  • 概念:JDBC(Java DataBase Connectivity) :Java数据库连接技术:具体讲就是通过Java连接广泛的数据库,并对表中数据执行增、删、改、查等操作的技术。如图所示:在这里插入图片描述
    此前我们学习过SQL后,可以通过 NavicatSQLyog等图形化客户端发送SQL操作数据库。本质上,JDBC的作用和图形化客户端的作用相同,都是发送SQL操作数据库。差别在图形化界面的操作是图形化、傻瓜化的,而JDBC则需要通过编码(这时候不要思考JDBC代码怎么写,也不要觉得它有多难)完成图形操作时的效果。
    总结:JDBC本质上也是一种发送SQL操作数据库的client技术,只不过需要通过Java编码完成。
  • 作用:
    通过JDBC技术与数据库进行交互,使用Java语言发送SQL语句到数据库中,可以实现对数据的增、删、改、查等功能,可以更高效、安全的管理数据。
    JDBC是数据库与Java代码的桥梁(链接)、
    

2 JDBC技术相关接口

  • 作用:JDBC要通过Java代码操作数据库,JDBC中定义了操作数据库的各种接口和类型:

    接口作用
    Driver驱动接口,定义建立链接的方式
    DriverManager工具类,用于管理驱动,可以获取数据库的链接
    Connection表示Java与数据库建立的连接对象(接口)
    PreparedStatement发送SQL语句的工具
    ResultSet结果集,用于获取查询语句的结果
  • JDBC是规范(接口)不是实现(类)
    JDBC 是一种规范,由Sum公司它提供了一套完整的接口,由数据库厂商根据特点予以实现,因此只要学会接口的使用就可以轻松的用 JDBC编写适用于各种数据库的程序。在这里插入图片描述

  • Mysql提供的JDBC实现
    Mysql提供的JDBC实现称为Mysql Connector,不同的数据库版本需要使用不同的Connector
    实际开发时根据数据库版本、JDK版本、选择不同的Connector

    Connector版本MySQL版本JDK版本
    8.05.6, 5.7, 8.0JDK 8.0 或更高
    5.15.6, 5.7, 8.0JDK 5.0 或更高

    下载地址:https://mvnrepository.com/artifact/mysql/mysql-connector-java
    为什么JDBC只有接口,没有提供实现?

不同数据库的底层技术不同,不少数据库是闭源的,源代码不公开的。Sun公司无力为所有数据库提供具体实现,只能提供接口而由数据库厂商提供具体实现,Sun公司只是制定JDBC标准,各个厂商准守标准提供具体的实现。JDBC和数据库实现的关系就好比List接口和ArrayList、LinkedList之间的关系。

面向JDBC接口规范编程,写出的JDBC代码可以在不同的数据库间轻松的迁移。

3 JDBC的编程步骤

  • JDBC操作数据库的步骤和 Navicat 操作数据库步骤就大同小异,下面我们先回顾下 Navicat的操作步骤,然后分析出JDBC的步骤。如图所示:在这里插入图片描述
  • JDBC开发六步
    1. 加载驱动
    2. 获取链接
    3. 准备SQL以及发送SQL的工具
    4. 执行SQL
    5. 处理结果集
    6. 释放资源
    
    1.打开IDEA如图所示的界面,点击Create New Project。 在这里插入图片描述
    2.选择Empty Java和点击Next,如图所示:在这里插入图片描述
    3.填写项目名称和点击Finish,如图所示:在这里插入图片描述
    4.点击File–>New–Module,如图所示:在这里插入图片描述
    5.选择Java,点击Next。如图所示:在这里插入图片描述
    6.填写子项目名称和点击Finish,如图所示:在这里插入图片描述

4 第一个JDBC程序

  • 准备工作:向 t_person 表中新增一行数据。
    create table t_person(person_id int primary key auto_increment,person_name varchar(20),age tinyint,sex varchar(6),mobile varchar(20),address varchar(200)
    );-- 需求 向t_person表中插入一行数据
    insert into t_person values(null,'王月华',88,'其他','138383838','硅谷');
    
    如图所示: 在这里插入图片描述
1、搭建开发环境
  • 在项目中引入数据库驱动jar包(jar文件:针对class文件的压缩格式包含了多个带包的class文件,类似于普通文件打包的zip、rar)。

  • eclipse

    将mysql-connector-java.jar添加到项目环境中
    1. 右键选中项目,新建一个folder名为lib,将jar包复制到lib目录中。
    2. 右键选中jar包,build path-->add to build path。
    
  • idea

    将mysql-connector-java.jar添加到项目环境中。
    1. 右键选中项目,新建一个Directory名为lib,将jar包复制到lib文件夹中。
    2. 右键选中jar包,Add as Library --> OK。
    

    如图所示:
    在这里插入图片描述 在这里插入图片描述在这里插入图片描述

2 JDBC访问数据库
  • 编码:
    Applications no longer need to explicitly load JDBC drivers using Class.forName(). 
    应用程序不再需要使用Class.forName()显式加载JDBC驱动程序。Existing programs which currently load JDBC drivers using Class.forName() will continue to work without modification 
    当前使用Class.forName()加载JDBC驱动程序的,将继续工作而不进行修改。
    

演示的代码如下:

package com.txw.jdbc;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
@SuppressWarnings("all")   // 注解警告信息
public class JdbcTesrt {public static void main(String[] args) throws Exception {// 1.连接驱动类Class.forName("com.mysql.cj.jdbc.Driver");// 2.获取连接// 数据库用户名String username = "root";// 数据库密码String password = "123456";/*url参数用来确定连接的数据库信息: 数据库机器ip 端口号port 数据库名db_name 连接的参数,比如编解码集、时区...url格式:jdbc:mysql://ip:port/db_name?k=v参数 ,只需要了解url的组成,不需要记忆*/String url = "jdbc:mysql://192.168.64.128:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai";Connection conn = DriverManager.getConnection(url,username,password);// url错误创建链接时会出现异常// 参数错误不会导致运行时异常System.out.println( conn );// 3.准备发送SQLString sql = "insert into t_person values(null,'Adair',25,'T','1383838381','硅谷');";PreparedStatement pstm = conn.prepareStatement(sql);// 4.发送执行SQLint update = pstm.executeUpdate();System.out.println( update );// 5.(如果是查询语句,需要处理结果集)// 6.关闭资源pstm.close();conn.close();}
}

如图所示:在这里插入图片描述

  • 参数解释:
    1. useUnicode = true&characterEncoding=UTF-8:mysql编码默认为GBK,此参数的作用就是允许插入unicode字符集中的数据,使用UTF-8编码方式进行编码。
    2. useSSL=false: SSL是高版本Mysql提供的数据加密、安全保障的新协议,为了向下兼容所以设置为false关闭此协议。
    3. serverTimezone=Asia/Shanghai:为了确保日期类型数据能够正确存储,需要指定时区为上海时区(上海时区与北京一致),默认为美国时区。
    
3 结果集的处理
  • 需求:查询t_person表中的数据。
    select * from t_person;
    

如图所示:在这里插入图片描述

  • 开发步骤回顾
    1 加载驱动
    2 创建和数据库之间的连接
    3 准备一个发送SQL的工具
    4 发送并执行SQL
    5 处理结果集
    6 释放资源。
    
  • 演示的代码如下:
package com.txw.jdbc;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@SuppressWarnings("all")   // 注解警告信息
public class JdbcTest01 {public static void main(String[] args) throws Exception {// 1.加载驱动Class.forName("com.mysql.cj.jdbc.Driver");// 2 创建和数据库之间的连接String username = "root";String password = "123456";String url = "jdbc:mysql://192.168.64.128:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai";Connection conn = DriverManager.getConnection(url,username,password);// 3.准备发送SQLString sql = "select * from t_person";PreparedStatement pstm = conn.prepareStatement(sql);// 4.执行SQL,接收结果集ResultSet rs = pstm.executeQuery();// 5 处理结果集while(rs.next()){/*rs.getXxx(列顺序从1开始) 或者 rs.getXxx("列名") 获取指定列的数据,Xxx为数据类型实战中多使用列名,可读性强*//*int personId2 = rs.getInt(1);String personName2 = rs.getString(2);int age2 = rs.getInt(3);String sex2 = rs.getString(4);String mobile2 = rs.getString(5);String address2 = rs.getString(6);System.out.println("personId="+personId2+",personName="+personName2+",age="+age2+",sex="+sex2+",mobile="+mobile2+",address="+address2);*/int personId1 = rs.getInt("person_id");String personName1 = rs.getString("person_name");int age1 = rs.getInt("age");String sex1 = rs.getString("sex");String mobile1 = rs.getString("mobile");String address1 = rs.getString("address");System.out.println("personId="+personId1+",personName="+personName1+",age="+age1+",sex="+sex1+",mobile="+mobile1+",address="+address1);}// 6.释放资源rs.close();pstm.close();conn.close();}
}

如图所示:在这里插入图片描述

  • PreparedStatement常用方法

    方法声明作用
    int executeUpdate(String sql)可执行增,删,改,返回执行受到影响的行数
    ResultSet executeQuery(String sql)执行SQL查询,并返回ResultSet对象
    boolean execute(String sql)可执行任何SQL语句,返回一个布尔值,表示是否返回ResultSet 。(只有执行查询才为true)
  • ResultSet常用方法

    方法声明作用
    boolean next()游标下移,判断该行是否有结果
    xx getXx(int index)获取该行结果中某个字段的数据,index为编号,index从1开始
    xx getXx(String name)获取改行结果中某个字段的数据,name为字段名

    xx为数据类型, 如图所示:在这里插入图片描述

5 数据绑定

  • 作用:数据绑定:将用户输入的数据,绑定到要执行的SQL语句中。
    JDBC执行的SQL中的数据要根据用户的输入发生变化,比如 登录功能背后的查询sql要根据用户名不同,执行不同的条件。这就需要将用户输入的数据绑定到执行的SQL中。
  • 准备工作:建表t_user 插入测试数据.
    create table t_user(user_id int primary key auto_increment,username varchar(20) unique not null,password varchar(50) not null
    );-- 添加测试数据
    insert into t_user values(null,'Adair','123456');
    

如图所示:在这里插入图片描述

1 字符串拼接SQL
  • 步骤:
    1. 在需要数据的地方,使用变量名替换。
    2. 在变量名前添加"+,变量后添加+"。
    3. 注意:如果拼接的是字符串,那么需要在"+之前添加' 在+"后添加'。
    
    演示:根据用户输入的id进行查询。
package com.txw.jdbc;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Scanner;
public class JdbcTest02 {public static void main(String[] args) throws Exception{// 用户输入数据Scanner sc = new Scanner(System.in);String id = sc.nextLine();// 1.加载驱动Class.forName("com.mysql.cj.jdbc.Driver");// 2.创建链接String dbUsername = "root";String dbPassword = "123456";String url = "jdbc:mysql://192.168.64.128:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai";Connection conn = DriverManager.getConnection(url,dbUsername,dbPassword);// 3.准备执行SQLString sql = "select * from t_user where user_id = "+id+";";PreparedStatement pstm = conn.prepareStatement( sql );// 4.执行SQL获取结果集ResultSet rs = pstm.executeQuery();// 5.处理结果集while( rs.next() ){Integer userId = rs.getInt("user_id");String username = rs.getString("username");String password = rs.getString("password");System.out.println(userId + "\t" + username + "\t" + password);}// 6.关闭资源pstm.close();conn.close();}
}

如图所示:

2、SQL注入问题
  • 使用字符串拼接SQL出现的问题。
    在进行查询操作时 恶意填入or 1=1 这类字符,使将要执行的sql变为无条件查询语句,泄漏数据或无法正确验证。
    

演示:

Scanner sc = new Scanner(System.in);
String id = sc.nextLine();//输入 1 or 1=1String sql = "select * from t_user where user_id = "+id+";";
//拼接后:select * from t_user where user_id =1 or 1=1 
3、?占位符
  • ?占位符是JDBC的一种特殊语法,专用于参数绑定,可以有效避免SQL注入问题。
    使用步骤:
    1. 在需要使用数据的地方,使用?代替(占位)。
    2. 发送sql前,通过pstm.setXXX(index,数据)方法给?赋值。
    index:占位符编号,从1开始,表示第几个占位符。
    xxx 为数据类型,需要根据数据库字段类型选择对应的赋值方法。
    
    例:在数据库中插入用户输入的数据。
package com.txw.jdbc;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.Scanner;
public class JdbcTest04 {public static void main(String[] args) throws Exception {// 用户输入数据Scanner sc = new Scanner(System.in);System.out.println("请输入用户名:");String name = sc.next();System.out.println("请输入年龄:");int age = sc.nextInt();System.out.println("请输入性别:(男/女)");String sex = sc.next();System.out.println("请输入手机号:");String mobile = sc.next();System.out.println("请输入地址:");String address = sc.next();// 1.加载驱动Class.forName("com.mysql.cj.jdbc.Driver");// 2.创建和数据库之间的连接String username = "root";String password = "123456";String url = "jdbc:mysql://192.168.64.128:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai";Connection conn = DriverManager.getConnection(url,username,password);// 3.准备执行SQL,数据使用?占位String sql = "insert into t_person values(null,?,?,?,?,?);";PreparedStatement pstm = conn.prepareStatement(sql);// 为?占位符赋值pstm.setString(1,name);pstm.setInt(2,age);pstm.setString(3,sex);pstm.setString(4,mobile);pstm.setString(5,address);// 4.执行SQLpstm.executeUpdate();//5.关闭资源pstm.close();conn.close();}
}

如图所示: 在这里插入图片描述
演示:解决SQL注入问题。

package com.txw.jdbc;import java.sql.*;
import java.util.Scanner;
public class JdbcTest05 {public static void main(String[] args) {Connection conn = null;PreparedStatement pstm = null;try {// 用户输入数据Scanner sc = new Scanner(System.in);String id = sc.nextLine();// 1.加载驱动Class.forName("com.mysql.cj.jdbc.Driver");// 2.创建和数据库之间的连接String username = "root";String password = "123456";String url = "jdbc:mysql://192.168.64.128:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai";conn = DriverManager.getConnection(url,username,password);// 3.准备执行SQL,数据使用?占位String sql = "select * from t_user where user_id = ? ";pstm = conn.prepareStatement( sql );// 为?占位符赋值pstm.setString(1,id);// 4.执行SQLResultSet rs = pstm.executeQuery();// 5.处理结果集while( rs.next() ){Integer userId = rs.getInt("user_id");username = rs.getString("username");password = rs.getString("password");System.out.println(userId + "\t" + username + "\t" + password);}}catch (Exception e ){e.printStackTrace();}finally {// 6.关闭资源try {pstm.close();} catch (SQLException throwables) {throwables.printStackTrace();}try {conn.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}
}

如图所示:在这里插入图片描述

6 JDBC异常处理

  1. 定位问题(哪一行出错)
    1. 添加打印语句,检查程序执行流程。
    2. 根据异常信息定位(找到异常信息中关于自己写的代码部分)。
    
  2. 单元测试更容易定位问题
    以某个小功能为单位进行测试,例如将用户输入的数据插入到数据库。
    1. 完成用户输入的数据,测试运行。
    2. 完成数据库Connection对象的创建,测试运行。
    3. 准备执行SQL语句,测试运行。
    4. 为?占位符赋值并执行SQL,测试运行。
    
  3. 根据异常日志分析
    分析异常最高效的办法是阅读异常日志,根据异常日志的信息,可以快速定位问题的位置、问题的原因设置是问题的解决方案。
    演示:
    Exception in thread "main" java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driverat java.net.URLClassLoader.findClass(URLClassLoader.java:382) // 数字指的是代码行号at java.lang.ClassLoader.loadClass(ClassLoader.java:418)at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355)at java.lang.ClassLoader.loadClass(ClassLoader.java:351)at java.lang.Class.forName0(Native Method)at java.lang.Class.forName(Class.java:264)at com.baizhi.test.ResultSetTest.main(ResultSetTest.java:8)
    
    调试步骤:
    1. 先看异常类型:ClassNotFoundException: com.mysql.cj.jdbc.Driver,说明是驱动类文件没有找到。
    2. 再看异常位置:自上而下看出现数字的行,找到自己写的代码。比如当前案例下:自己的代码 ResultSetTest.java第8行有问题,那么错误就在这里发生的。
    3. 解决方案:com.mysql.cj.jdbc.Driver类没找到,这行代码是加载驱动类的,就一定要先找到对应的类。
    4. 错误原因:1.包名或类名可能写错了。 2.如果包名与类名完全正确,检查驱动jar包没有导入当前项目中。
    
    说明:阅读异常日志挑错是最有效的,但是对于初学者而言难度过高。刚开始不用急于求成,异常信息也非常有规范,在学习过程中慢慢提升异常阅读能力,最终掌握阅读异常信息的能力。
  4. 快速掌握JDBC中的常见异常处理方案
    JDBC的异常其实还是非常固定的,就那么几种:类加载问题、数据库用户名密码错误、sql语法错误、绑定数据错误、获取数据错误…
    有1个办法可以快速的掌握JDBC中的异常:
    站在上帝视角,人为的造错,观察记录异常信息,日后出现时可以快速调错。

http://chatgpt.dhexx.cn/article/hZfBshrR.shtml

相关文章

JDBC 连接 MySQL

哈喽~大家好,这次我们来看看 JDBC 如何 连接 MySQL. 目录 一、开头 二、介绍 1、JDBC 的概念 2、JDBC 的功能 3、JDBC 的常用接口和类 三、数据库的创建(MySQL) 1、连接 MySQL (1)、注册驱动 (2)、获取连接 (3)、获取执行者连接 …

BindingNavigator 类 - MSDN

.NET Framework 2.0 其他版本 5(共 9)对本文的评价是有帮助 - 评价此主题 注意:此类在 .NET Framework 2.0 版中是新增的。 表示窗体上绑定到数据的控件的导航和操作用户界面 (UI)。 命名空间:System.Windows.Forms 程序集:System.Windows.Fo…

Android的一个BindView工具的实现

对于Android已经有很多Bind View的工具了,大多都是使用了反射和注解的方法。那么如何实现一个简易的代码生成工具呢?其实不难,只要会写代码都可以试试。这些天,我试了一下,并将它做成了工具。代码如下: pa…

setNavigationBarTitle

wx.setNavigationBarTitle就是用来改红框框里面的内容滴 在项目开发中经常用到 使用的场景就包括了多个地方用同一套页面的时候 wx.setNavigationBarTitle({title: "我的店铺",});

安卓ViewBinding详解

背景 之前我们通过Kotlin Android Extensions来访问布局文件中的元素,但是这个现在被废弃了,原因如下: 空安全:res下的任何id都可以被访问,有可能因访问了非当前Layout下的id而出错兼容性:只能在kotlin中…

Winform中用bindingNavigator和bingdingSource实现分页

BindingNavigator控件介绍 可以使用BindingNavigator控件来创建标准化的方法,以便用户搜索和更改 Windows 窗体上的数据。BindingNavigator 控件由包含一系列 ToolStripItem 对象的ToolStrip组成,可以实现:添加数据,删除数据&…

DataGridView使用bindingNavigator实现分页功能(应用存储过程)

想法是这样的:使用bindingNavigator存储过程实现DataGridView的分页功能,其中包含简单的查询。 存储过程如下: --创建分页查询存储过程(含输出参数,输入参数(含搜索功能)) use HotelDB if exists(select *…

配置bind

安装bind yum install bind-* service firewalld stop #暂时关闭防火墙 vim /etc/named.conf Linsten-on port 53 {any;}; 监听除了自己以外的ip Allow-query{any;} 允许任意的ip来访问 配置正向解析 /etc/named.rfc1912.zones #直接在底部添加 zone "s…

Android dataBinding和viewBinding的混淆配置

在最近重构过的项目中有使用dataBinding或viewBinding,在调试的时候没有问题,但是在混淆过后出现了崩溃: 我们知道viewbinding的初始化是ActivityMainBinding.inflate() 而我是通过反射去初始化viewbinding的 很明显,布局所生成的…

viewBinding和@BindView的用法的简单使用

viewBinding 1.module下的build.gradle,在闭包android{ }里面添加 viewBinding {enabled true} 2.使用方法 用视图绑定功能后,系统会为该模块中包含的每个 XML 布局文件生成一个绑定类。这个类的类名是以xml布局文件名去掉下换线后,单词…

BindingNavigator控件

WinForm之中BindingNavigator控件的使用 在微软WinForm中,BindingNavigator控件主要用来绑定数据。可以将一个数据集合与该控件绑定,以进行数据 联动的显示效果。如图下图所示: 那么,下面我们就来用BindingNavigator控件做一下上图…

WinForm控件之【BindingNavigator】【DataSet】【BindingSource】【DataGridView】

基本介绍 数据类控件,数据加载绑定便捷应用相当广泛,具体看例子自行扩展吧; 常设置属性 BindingNavigator--BindingSource:数据来源,绑定后默认项会根据相应的操作按钮执行操作; BindingNavigator--Items&a…

WinForm之中BindingNavigator控件的使用

在微软WinForm中,BindingNavigator控件主要用来绑定数据。可以将一个数据集合与该控件绑定,以进行数据联动的显示效果。如图下图所示: 那么,下面我们就来用BindingNavigator控件做一下上图所示的效果。 分析:该案例以B…

winform控件之BindingNavigator

BindingNavigator控件可以为我们绑定的数据提供一个导航的功能,默认的工具是这个样子的,我们可以根据需求再增加功能 1.BindingNavigator用法 1.1界面布局 界面布局如下 一个BindingNavigator名为bindingNavigator1 一个DataGridView名为DataGridVie…

C#开发之——ToolStrip(10.22)

一 概述 在C# WinForm开发中添加工具栏(ToolStrip)和添加菜单栏类似&#xff0c;在工具箱中将ToolStrip控件直接拖到Windows窗体中即可 <!--more--> 二 ToolStrip操作 从工具箱拖拽ToolStrip控件到Windows窗体后&#xff0c;如下图所示(在添加了ToolStrip控件之后&…

C#winform窗体控件之toolStrip

C#winform窗体控件之toolStrip 在做窗体时我们可能需要一个工具栏&#xff0c;那这时最简单的方法就是添加一个toolStrip控件。 如何完成一个上图的工具栏呢? 首先&#xff0c;需要添加一个toolStrip控件&#xff0c;然后点击控件上的添加按钮&#xff0c;添加你需要的控件&…

C#如何让ToolStrip工具栏按钮分别靠左和靠右对齐分布

ToolStrip工具栏按钮默认靠左对齐&#xff0c;如何让ToolStrip工具栏按钮分别靠左和靠右对齐分布&#xff1f;&#xff01; 第一步&#xff0c;选择要靠右对齐的工具栏上的按钮&#xff0c;属性&#xff0c;设置“Alignment: Right” 即&#xff0c;this.toolStripSysInfoBut…

ToolStrip

&#xfeff;&#xfeff; 效果实现&#xff1a; 1.添加ToolStrip控件 2.点击ToolStrip控件添加button,设置Imagine,对ToolStripButton的Text进行设置,DisplayStyle设置为ImagineAndText即可。

ToolStrip控件中如何添加功能按钮

1&#xff0c;在工具箱中选择ToolStrip控件 2&#xff0c;在属性框&#xff0c;选择item 3,进入该界面&#xff0c;选择添加类型 4&#xff0c;指定选定控件的类型 name:控件的名字&#xff0c;相当于对象名。 text&#xff1a;指定控件中内容限制字段 image&#xff1a;指…