前言❤️❤️
hello hello💕,这里是洋不写bug~😄,欢迎大家点赞👍👍,关注😍😍,收藏🌹🌹
接下来进入mysql入门的最后一个部分,数据库JDBC编程,这篇博客的知识点比较细,从驱动准备到关闭连接,大部分都是大家之前没有接触过的概念,铁汁们暂时看不懂的概念直接跳过就行,最后从头到尾练习下代码,基本上就能掌握了🐵
🎇个人主页:洋不写bug的博客
🎇所属专栏:数据库
🎇mysql8.0和navicate的安装:mysql安装教程
🎇铁汁们对于MySQL数据库的各种常用核心语法,都可以在上面的数据库专栏学习,专栏正在持续更新中🐵🐵,有问题可以写在评论区或者私信我哦~
1,简介
JDBC就是Java Data Base Connectivity(Java数据库连接)首字母的简写
JDBC包含了一套Java定义的用于执行SQL语句的接口(只定义方法,没有具体的实现),使开发者能够编写数据库程序,是Java程序和数据库之间的桥梁
JDBC的主要作用:与数据库建立连接,发送SQL语句和处理数据库执行结果
直接看概念可能会觉得比较抽象,下面就看下过程:
Java程序去操作数据库的话,不同的数据库有不同的协议(比如说连接方式不同,组织数据的方式不同)
那能不能定义一个通用规范,让Java程序来对不同数据库的操作代码都相同
比如 “获取连接” 就都使用getConnection(),“执行查询” 都使用executeQuery(),这样程序员在Java中操作数据库就会很方便
“JDBC” 本身是 Java 定义的通用规范(接口),JDBC内部的驱动是由各个数据库厂商来开发的,因为他们对数据库的协议也比较了解

JDBC的使用过程就可以概括为:
- 加载数据库厂商的驱动包
- 建立连接
- 创建Statement
- 执行SQL
- 处理结果释放资源,关闭连接
2,下载JDBC驱动
我们这里使用的是MySQL数据库,既然不同的数据库的JDBC驱动程序不同,那在Java中写代码前就要先搞下驱动
首先在IDEA中创建项目,选择Maven构建系统,可能在JavaSE学习的时候使用的都是Intellij构建系统,但是实际开发中更多都是使用Maven

Maven定义了工程在构建过程中的一些约定,让测试,打包,访问静态资源变得统一
例如这里src目录里分为了test目录和main目录,main目录中是Java项目开发时的源代码和静态资源文件,test目录中是用于测试的代码,生成jar包时并不会包含test目录中的内容
下面有个pom.xml,就是项目中关于Maven的配置文件

创建Maven还有个好处,那就是Maven 中央仓库中包含了绝大多数主流数据库的 JDBC 驱动,我们可以直接在pom.xml(配置文件)中通过依赖配置引入,无需手动下载和管理
刚刚提到说不同数据库的JDBC驱动是不同的,如果不用Maven,就要从数据库官网中找,比较麻烦,而Maven中央仓库就类似于手机上的应用市场,可以快速的配置JDBC驱动
打开Maven依赖检索平台(在Maven中,依赖除了 JDBC 驱动,还包括其他工具库、框架),链接已经放在下面了
Maven依赖检索平台
输入Mysql搜索,会发现有两个JDBC驱动,第一个后面带有J,就是当前最新版本;
第二个就是相对比较老的版本



使用比较经典的8.0.33版本,第一个和第二个里面都收录了,在第一个和第二个里面找都可以,点击8.0.33,点击后就进入了这样的一个界面,复制下面框里的内容(在下图中已圈出)

接着回到IDEA中,打开pom.xml配置文件,在properties标签后写上一个dependencies标签,接着把东西复制到这个标签中,

这时候点击一下右上角的这个按钮,Maven 就会从中央仓库下载对应的 JDBC 驱动 JAR 包,并将其引入到项目中,让你的 Java 程序能够使用该驱动来操作数据库,点击完下载后就会发现这里也不爆红了


Maven仓库的地址在国外,因此可能有少部分铁汁下载依赖的时候会特别慢,甚至卡住,这时候就可以把仓库镜像配置成国内的(如果能成功下载依赖的铁汁们就不需要改镜像了)
右键IDEA程序,点击打开文件所在位置

进入文件位置后,找到刚进入IDEA这一层(点击上一层即可到达)

打开plugins目录,根据这个路径来找到配置文件settings.xml,先拷贝一份,防止一会改错

接着用记事本打开这个配置文件,找到mirrors这部分,这里面就是默认仓库镜像配置,把这部分用阿里的镜像来替代

把mirrors整部分都用下面这个来替代,这时候改成了阿里云的镜像配置,以后下载依赖走的就是阿里云的路径,速度就会比较快
<mirrors>
<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
<mirror>
<id>central</id>
<mirrorOf>*</mirrorOf>
<name>aliyun central</name>
<url>https://maven.aliyun.com/repository/central</url>
</mirror>
<mirror>
<id>spring</id>
<mirrorOf>*</mirrorOf>
<name>aliyun spring</name>
<url>https://maven.aliyun.com/repository/spring</url>
</mirror>
</mirrors>
3,表的准备
这里博主在first_database的数据库里创建一个student表,在里面加入数据
CREATE TABLE student (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
age INT,
gender VARCHAR(10)
);
INSERT INTO student(name,age,gender) VALUES("marrie",18,"女"),("mark",20,"男"),("helena",19,"女");

4,JDBC的使用
JDBC的使用过程就可以概括为:
- 加载数据库厂商的驱动包
- 建立连接
- 创建Statement
- 执行SQL
- 处理结果集
- 处理结果释放资源,关闭连接
1,驱动加载
在Java目录下创建个Demo01_DriverManager类,在里面写代码

在main方法中写上Class.forName(),加载mysql驱动,然后alt + enter键捕获一下异常,这段代码的作用就是加载数据库厂商提供的驱动,让MySQL的jar包和Java环境建立联系
代码就是下面这样:
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
Class.forName就是加载指定的类,这里加载Driver类,经过一系列里面方法的调用执行,就加载并注册 MySQL JDBC 驱动
点击ctrl键点击一下这个Driver,就进入到了数据库实现的Driver类中,可以看下这个类的位置,在jdbc包下,如下所示:

这个类就是由MySQL数据厂商实现的JDBC驱动类,实现了JDBC的Driver接口,前面提到过,不同的数据库协议不同,但是数据库厂商都会基于这些接口规范来实现类,确保无论什么数据库程序员写的操作代码都是一样的
里面的代码就是完成驱动的注册,驱动只有在注册后才能使用

2,建立数据库连接
在前一段代码的基础上加上这段代码,这个url直接复制下,然后改下端口号和要访问的数据库的名称就可以了,具体的信息博主标在下面的图上了,大家可以看下
这里回环地址大家直接复制就可以,就是代表连接本机,博主因为之前装过MySQL5.7版本,所以端口号是3308,大家第一次安装mysql端口号应该是3306,实在不确定的话可以写SQL语句查下(如下所示)


这里面除了url,还有两个参数,一个是user,一个是passward,就是用户和密码
这里user这里写root,就是数据库的默认超级管理员用户名,后面写下密码(这里博主的密码是123456,这个密码就是打开mysql命令行工具刚开始要输入的那个密码),在alt enter 一下语句捕获个异常
接着创建个connection变量,把连接赋给变量,建立数据库的连接这部分就完成了,代码如下
try {
// 1,加载数据库厂商提供的驱动,让MySQL的jar包和Java环境建立联系
Class.forName("com.mysql.cj.jdbc.Driver");
// 2,建立数据库连接
Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3308/first_database?characterEncoding=utf8" +
"&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false", "root", "123456");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (SQLException e) {
throw new RuntimeException(e);
}
这里大家把url复制下来,改一下端口号(大部分铁汁的端口号还是3306),改下数据库名字(把这里的first_database改成你的数据库的名字)
3,创建Statement和执行sql
这段代码也是在try这个代码块里面写的,首先创建一个 Statement 类型的变量statement,接着写个字符串,里面是查询的SQL语句,查询就调用executeQuery方法,修改数据就调用executeUpdate方法
这里是查询语句,就用statement调用executeQuery方法,发送 SQL 语句到数据库、执行并返回结果,通过resultSet变量来接收(ResultSet是一个接口,resultset实现类对象的引用),代码如下所示:
try {
// 1,加载数据库厂商提供的驱动,让MySQL的jar包和Java环境建立联系
Class.forName("com.mysql.cj.jdbc.Driver");
// 2,建立数据库连接
Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3308/first_database?characterEncoding=utf8" +
"&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false", "root", "123456");
//3,创建Statement和执行sql
Statement statement = connection.createStatement();
String sql = "select id,name,age,gender from student"; //定义SQL语句
ResultSet resultSet = statement.executeQuery(sql); //执行SQL
}
(按住ctrl键点击Statement,会发现它是一个接口),这个变量存储了一个 Statement 接口实现类的对象的引用;变量 statement只是这个对象的引用(这部分可能有点抽象,铁汁们大概看下就行)

4,处理结果集
result.next()返回的是一个boolean值,true表示有下一条记录,这里就使用while循环来打印数据,用resultset的方法来获取这些数据,不同的数据类型对应着不同的方法,里面传入的列的索引,根据列在表中的位置来写,如下所示:

最后就是打印,使用Messageformat类的format方法,按照指定的格式拼接变量值,里面的 {0}、{1}、{2}、{3} 是占位符(数字表示位置索引,从 0 开始),后面的 id、name、age、gender 是要替换这些占位符的实际变量值。(这样写的话会比直接用字符串拼接简单很多,特别是表中的数据有很多列的时候)
while (resultSet.next()){
long id = resultSet.getLong(1);
String name = resultSet.getString(2);
int age = resultSet.getInt(3);
String gender = resultSet.getString(4);
System.out.println(MessageFormat.format("学号={0},姓名={1},年龄={2},性别={3}",id,name,age,gender));
}
5,释放资源,关闭连接
在对数据库操作完后,一定要释放资源,关闭连接,主要是以下两个原因:
- 数据库服务器能支持的并发连接数是有限的,如果使用后不关闭连接,这些连接会一直占用数据库资源,最终导致新的连接请求无法建立
- Connection、Statement、ResultSet等对象都属于非 Java 托管的本地资源,Java无法对他们进行垃圾回收,长期积累会导致内存溢出,程序崩溃
释放资源要在finally中完成,刚刚创建的顺序是Connection,Statement,ResultSet
释放资源的时候就要以相反的顺序来释放,这是因为Statement和ResultSet是依赖于Connection的,如果先去关Connection的话,那么Statement和ResultSet失去依赖,就会出现异常
在finally中写的话,刚刚创建的connection,statement,resultSet这些都是局部变量,没法使用,因此就要把它们改为全局变量,如下图

在finally中,写完close后,按下alt enter键,生成try,catch方法,代码就基本上ok了,代码如下:
finally { if(resultSet != null){ try { resultSet.close(); } catch (SQLException e) { throw new RuntimeException(e); } } if(statement != null){ try { statement.close(); } catch (SQLException e) { throw new RuntimeException(e); } } if(connection != null){ try { connection.close(); } catch (SQLException e) { throw new RuntimeException(e); } } }代码全部写完后运行,结果就是这样的:

6,源码
import javax.xml.transform.Result; import java.sql.*; import java.text.MessageFormat; public class Demo01_DriverManager { public static void main(String[] args) { Connection connection = null; Statement statement = null; ResultSet resultSet = null; try { // 1,加载数据库厂商提供的驱动,让MySQL的jar包和Java环境建立联系 Class.forName("com.mysql.cj.jdbc.Driver"); // 2,建立数据库连接 connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3308/first_database?characterEncoding=utf8" + "&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false", "root", "123456"); //3,创建Statement和执行sql statement = connection.createStatement(); String sql = "select id,name,age,gender from student"; //定义SQL语句 resultSet = statement.executeQuery(sql); //执行SQL //4,遍历结果集,获取数据行,resultSet.next()返回一个boolean值,true表示有下一条记录 while (resultSet.next()){ long id = resultSet.getLong(1); String name = resultSet.getString(2); int age = resultSet.getInt(3); String gender = resultSet.getString(4); System.out.println(MessageFormat.format("学号={0},姓名={1},年龄={2},性别={3}",id,name,age,gender)); } } catch (ClassNotFoundException e) { throw new RuntimeException(e); } catch (SQLException e) { throw new RuntimeException(e); }finally { if(resultSet != null){ try { resultSet.close(); } catch (SQLException e) { throw new RuntimeException(e); } } if(statement != null){ try { statement.close(); } catch (SQLException e) { throw new RuntimeException(e); } } if(connection != null){ try { connection.close(); } catch (SQLException e) { throw new RuntimeException(e); } } } } }5,扩展使用
如果要根据学生的名字来查询这行的数据,每次都重新写sql字符串比较麻烦
能不能直接在IDEA控制台上输入学生的名字,然后在数据库中进行查询,将查询到的数据在控制台中打印出来只需要在刚才的代码上进行微调即可,主要的修改都在创建Statement和执行sql部分
//3,创建Statement和执行sql statement = connection.createStatement(); System.out.println("请输入您要查询的名字-->"); Scanner scanner = new Scanner(System.in); String inputName = scanner.next(); String sql = "select id,name,age,gender from student where name = '" + inputName + "'"; //定义SQL语句 resultSet = statement.executeQuery(sql); //执行SQLString sql = "select id,name,age,gender from student where name = '" + inputName + "'"; //定义SQL语句这里要注意的是如何把inputName加到sql语句中去,直接查询,应该是这样的,名字加个单引号,因此这里也要拼接出一个单引号

一般也习惯在这里也改为把while改为if,表示一次只查询一条数据

6,SQL注入
那铁汁们看下,如果在IDEA控制台上这样输入,强行把后面那个单引号给注释掉,加上个or语句

这个的sql语句就相当于是这样,在navicat中运行下,会直接把所有数据都查出来,并不会报错

但是在IDEA中运行下,就直接报错了,这是为什么呢?

这是因为官方的依赖中做了对–这些特殊字符的过滤,另外检测到使用or语句也会阻止访问
特殊字符用特殊语句构造一个合法的SQL语句,得到结果,就是SQL注入,官方依赖中队特殊字符的过滤就是为了抵制SQL注入,可以有效的防止数据库遭到恶意入侵在互联网早期,数据库厂商的官方依赖并没有内置针对 SQL 注入的特殊字符过滤机制,开发者也不注重防御,
如果攻击者在登录页面进行SQL注入,if虽然只查询第一条数据,但是第一条数据一般是管理员的账号和密码信息,而且很多都是明文,没有加密,这时候攻击者就能用管理员身份来登入网站,对网站进行破坏,这也就是SQL注入攻击那么MySQL数据库厂商依赖中的特殊字符过滤就是万能的吗?
- 既然SQL会过滤 -- ,#也可以注释,那试下#
- 既然or的使用会被检测到,那把or分隔开呢
代码就像下面这样:

接着在IDEA中试一下,会发现这样确实绕过了对特殊字符的检测,可以访问到第一条数据

那如何更强的防御sql注入呢,这就是下篇数据库博客要聊的内容了🐵
注意:SQL 注入属于非法侵入计算机信息系统、窃取数据或破坏系统的行为,在全球主要国家和地区的法律中都是明确禁止的,因此建议铁汁们也不要去随意尝试😅🐵
结语💕💕
这部分知识还是很杂,很多的,初学铁汁们最重要的是把源码练习几遍,先把代码写熟了,后面再慢慢理解
以上就是今天的所有内容啦~完结撒花~🥳🎉🎉


2323



被折叠的 条评论
为什么被折叠?



