【MySQL】使用 JDBC 连接数据库

JDBC 连接数据库

文章目录

  • 前言
  • 1. 认识 JDBC
    • 1.1 概念
    • 1.2 好处
  • 2. 使用 JDBC
    • 2.1 安装数据驱动包
    • 2.2 把 jar 包导入到项目中
    • 2.3 代码编写
    • 2.4 测试结果
  • 3. 代码优化
  • 4. 源码展示
  • 结语


前言

在 MySQL 系列中,我们介绍了很多内容,包括但不限于建库建表,增删查改等等,但是这些操作都是直接在本机上的 MySQL 进行的,而在实际的开发过程中,我们很少会这样做,更多的是通过代码(C++、Java、Python……)来操作数据库的。今天我们就会简单介绍如何通过 Java 代码来操作数据库


1. 认识 JDBC

1.1 概念

JDBC(Java Database Connectivity)是一个 Java API,它提供了一种标准的方法,用于 Java 程序与各种数据库进行交互。简单来说,JDBC 是一个桥梁,使得 Java 应用程序能够执行 sql 语句,以查询、更新和管理数据库中的数据


1.2 好处

  1. 平台无关性:JDBC 使我们可以在任何支持 Java 的平台上运行的数据库访问代码,而无需关心底层数据库的类型
  2. 数据库无关性:JDBC 提供了统一的 API,使得我们可以使用相同的代码结构来访问不同类型的数据库,如 MySQL、Oracle、SQL Server 等
  3. 简化数据库访问:JDBC 简化了数据库访问的过程,我们不需要深入了解底层数据库的复杂性,就可以通过 JDBC 提供的接口轻松地执行数据库操作

2. 使用 JDBC

2.1 安装数据驱动包

所谓的数据驱动包,实际上就是包含了 JDBC 操作数据库的 API 的一个 jar 包,里面有很多的 .class 文件,我们可以在官网下载驱动包 (https://dev.mysql.com/downloads/)

也可以在 Maven 中央仓库下载(https://mvnrepository.com/),此处我们简单演示一下在 Maven 下载数据驱动包

  • 打开 Maven 网址,搜索栏输入“Mysql”,此时最上面会出现两个结果。因为博主使用的 MySQL 版本比较老,所以选择 “经典版”

    请添加图片描述

  • 点进去后就是各种版本的驱动包了。这里需要下载和你 MySQL 安装的版本一致才可,我的MySQL是 5.7 的,所以要选择 5.1 开头的,后面的小版本无所谓;如果你的 MySQL 是 8.x 版本的,那你就要选择 8 开头的驱动包了

    image-20241007201415044

  • 博主这里选择 5.1.49 这个版本,点进去后下载 jar

    请添加图片描述

  • 这样就下载好啦~

    image-20241007202832069


2.2 把 jar 包导入到项目中

  • 先新建一个 Java 项目,并在这个项目下右键建立一个目录,命名为 lib(注意不要带有中文/特殊字符)

    请添加图片描述

  • 接着找到我们下载好的 jar 包,直接复制然后粘贴到 lib 目录中(ctrl c 和 ctrl v 即可),点击 OK

    image-20241007202911979

  • 然后右键 lib 目录,点击 add as library,再点击 OK 就行了。此时 idea 就能自动分析出 jar 包里有什么内容了

    image-20241007203302880

    image-20241007203404120

  • 这样就大功告成啦

    image-20241007203514612


2.3 代码编写

1. 创建数据源:要连接数据库时,我们需要知道这个数据库的位置;我们可以通过 DataSource 对象来获取

        DataSource dataSource = new MysqlDataSource();
        ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/javatest?characterEncoding=utf8&useSSL=false"); // “Javatest”是数据库名
        ((MysqlDataSource)dataSource).setUser("root");
        ((MysqlDataSource)dataSource).setPassword("xxxxxxxxx"); // 根据你安装是设置的密码填入
  • DataSourse 是 Java 中的一个接口,不能直接创建对象,因此我们使用 MysqlDataSource 这个子类来创建对象
  • 接下来是 setURL( )、setUser( )、setPassWord( ),它们都是 MysqlDataSource 中的方法,分别服务器的 url(统一资源定位符)、服务器的账号、服务器的密码()
  • 此处我们还使用了向上转型和向下转型,目的是为了降低耦合。若之后我们使用的数据库不是 MySQL,那修改代码就十分方便

2. 和数据库服务器建立网络连接

Connection connection = dataSource.getConnection();
  • 要注意此处的导入的包是 import java.sql.Connection 这个,不要选错了
  • 此处的 Connection 对象,表示的就是一个数据库连接(抽象的客户端服务器连接)
  • 此处的异常可以使用 throw 直接抛出

3. 构造 SQL 语句

比如我们现在想要在表中插入一条信息,就可以使用字符串来表示

String sql = "insert into student values ('qiqi', 77)";

接着使用 PreparedStatement 来预编译这个 sql 语句

PreparedStatement statement = connection.prepareStatement(sql);
  • 我们写的 sql 语句就可以放在 statement 这个对象里面
  • 预编译指的是它可以在客户端发送 sql 语句前,先解析一下,从而降低服务器的工作压力

4. 执行 SQL 语句

我们需要把 sql 发送到服务器上进行执行,可以使用 statement 里的方法

  • 如果我们要执行的是增、删、改的操作,那就使用 executeUpdate 方法

    statement.executeUpdate();
    
  • 如果我们要执行的是操作,那就使用 executeQuery 方法

    statement.executeQuery();
    

5. 断开连接,释放资源

在进行类似的网络通信时,在使用完后一定要记得释放资源。我们上面创建了 connectionstatement 两个对象,它们都需要释放,我们按照创造顺序的相反来关闭(先 statement,后 connection

statement.close();
connection.close();

完整代码如下:

package jdbc;

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;

public class TestUpdate {
    public static void main(String[] args) throws SQLException {
        //1.创建数据源对象(基本是默认的)
        DataSource dataSource = new MysqlDataSource();
        ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/javatest?characterEncoding=utf8&useSSL=false");
        ((MysqlDataSource)dataSource).setUser("root");
        ((MysqlDataSource)dataSource).setPassword("xxxxxxxxx");

        //2.和数据库服务器建立网络连接(选择Connection java.sql包)
        Connection connection = dataSource.getConnection();
        //System.out.println(connection);//测试连接是否成功

        //3.构造sql语句(基于PreparedStatement预处理)
        String sql = "insert into student values ('qiqi', 77)";//写死的

        //4.把sql发送到服务器上进行执行
        //statement.executeQuery()查询
        //statement.executeUpdate()增删改
        int n = statement.executeUpdate();//影响的行数
        System.out.println(n);

        //5.释放上述资源(倒着释放)
        statement.close();
        connection.close();
    }
}

2.4 测试结果

image-20241007213728395

最终打印 1,即影响的行数,表示插入成功


3. 代码优化

String sql = "insert into student values ('qiqi', 77)";//写死的
  • 我们这里是把插入的 sql 给写死了,如果我们能够在控制台输入我们需要插入的信息,岂不美哉。因此得把代码修改一下
        //用户输入
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入姓名:");
        String name = scanner.nextLine();
        System.out.println("请输入分数:");
        int grade = scanner.nextInt();

		//修改sql语句
		String sql = "insert into a values ('"+ name +"',"+ grade +")";
  • 这时候就可以通过控制台输入信息了。但是此处还有点小瑕疵,它有可能会引起 sql 注入攻击,别人可以通过代码直接拼接构造 sql 语句导致 sql 语句被恶意篡改(有一篇 2012 年的新闻报道了 sql 注入事件,感兴趣的可以看一下( 网传技术流号牌遮挡能干掉交警数据库 警方辟谣)

  • 所以我们可以把 sql 语句再修改一下,使用占位符 “ ?”

String sql = "insert into a values (?,?)";//?为占位符

接着通过 statement 对象里面的 setInt() 和 setString() 方法来设置这两个字段,从而将这个 sql 语句构造完整,这样就能防止 sql 注入攻击啦

PreparedStatement statement = connection.prepareStatement(sql);
statement.setInt(1, id);
statement.setString(2, name);

补充:数据库的查找操作

上面我们提到了,如果我们要执行的是操作,那就得使用 executeQuery 方法

除此之外,返回的结果也不一样:

  • 如果是增、删、改操作的话,返回的就只是一个 int 类型的值,表示影响的行数,可以检验 sql 语句是否执行成功
  • 但是对于操作,它会返回一个结果集,也就是我们查询的结果,因此我们可以使用ResultSet 对象来进行接收,接着遍历里面的内容。最后也要记得关闭它哦
  • 其他的代码就和上面的插入是一样的
package jdbc;

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class Testselect {
    public static void main(String[] args) throws SQLException {
        DataSource dataSource = new MysqlDataSource();
        ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/javatest?characterEncoding=utf8&useSSL=false");
        ((MysqlDataSource)dataSource).setUser("root");
        ((MysqlDataSource)dataSource).setPassword("xxxxxxxxx");

        Connection connection = dataSource.getConnection();

        String sql = "select * from student";
        PreparedStatement statement = connection.prepareStatement(sql);

        //一个集合类,可以遍历得到
        ResultSet resultSet = statement.executeQuery();

        //遍历结果
        while (resultSet.next()) {
            System.out.println(resultSet.getString("name"));
            System.out.println(resultSet.getInt("grade"));
        }

        resultSet.close();
        statement.close();
        connection.close();
    }
}

运行结果如下:

image-20241007215847008


4. 源码展示

插入操作

package jdbc;

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;

public class TestUpdate {
    public static void main(String[] args) throws SQLException {
        //0.用户输入
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入姓名:");
        String name = scanner.nextLine();
        System.out.println("请输入分数:");
        int grade = scanner.nextInt();

        //1.创建数据源对象(基本是默认的)
        DataSource dataSource = new MysqlDataSource();
        ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/javatest?characterEncoding=utf8&useSSL=false");
        ((MysqlDataSource)dataSource).setUser("root");
        ((MysqlDataSource)dataSource).setPassword("xxxxxxxxx");

        //2.和数据库服务器建立网络连接(选Connection java.sql包)
        Connection connection = dataSource.getConnection();
        //System.out.println(connection);//测试连接是否成功

        //3.构造sql语句(基于PreparedStatement预处理)
        //String sql = "insert into student values ('qiqi', 77)";//写死的
        //String sql = "insert into student values ('"+name+"',"+grade+")";
        //代码看起来乱,而且可能会被“sql注入攻击”---> ');drop database xxx;
        String sql = "insert into student values (?,?)";//?为占位符
        //String sql = "delete from a where name = ?";//删除也是一样
        PreparedStatement statement = connection.prepareStatement(sql); //预编译
        statement.setString(1,name); //1表示第一个问号
        statement.setInt(2,grade);

        //4.把sql发送到服务器上进行执行
        //executeQuery()查询
        //executeUpdate()增删改
        int n = statement.executeUpdate();//影响的行数
        System.out.println(n);

        //5.释放上述资源(倒着释放)
        statement.close();
        connection.close();
    }
}

查询操作

package jdbc;

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class Testselect {
    public static void main(String[] args) throws SQLException {
        DataSource dataSource = new MysqlDataSource();
        ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/javatest?characterEncoding=utf8&useSSL=false");
        ((MysqlDataSource)dataSource).setUser("root");
        ((MysqlDataSource)dataSource).setPassword("xxxxxxxxx");

        Connection connection = dataSource.getConnection();

        String sql = "select * from student";
        PreparedStatement statement = connection.prepareStatement(sql);

        //一个集合类,可以遍历得到
        ResultSet resultSet = statement.executeQuery();

        //遍历结果
        while (resultSet.next()) {
            System.out.println(resultSet.getString("name"));
            System.out.println(resultSet.getInt("grade"));
        }

        resultSet.close();
        statement.close();
        connection.close();
    }
}

结语

今天我们介绍了如何使用 JDBC 连接数据库,通过代码来直接操作 MySQL 数据库,上面展示的操作方法还是比较粗糙的,而且随着技术的不断更新,我们也很少会直接使用 JDBC 了。但是理解上述的操作方法对我们来说肯定是有作用,在后续使用框架的时候,底层原理还是离不开这个操作思路的。接下来是博主的一些碎碎念 (●’◡’●)

一个月没写博客了,有点生疏,加上需要回顾前面的知识以及查阅资料,确实需要消耗更多的时间。不知道值不值得继续✍,但是总觉得学习完一个知识点后不总结篇博客就不得劲,自己写的东西到时候来回顾应该也更加得心应手吧。接下来我更加努力更新博客,加油 (ง •_•)ง

希望大家能够喜欢本篇博客,有总结不到位的地方还请多多谅解。若有纰漏,希望大佬们能够在私信或评论区指正,博主会及时改正,共同进步

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

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

相关文章

微信步数C++

题目: 样例解释: 【样例 #1 解释】 从 (1,1) 出发将走 2 步,从 (1,2) 出发将走 4 步,从 (1,3) 出发将走 4 步。 从 (2,1) 出发将走 2 步,从 (2,2) 出发将走 3 步,从 (2,3) 出发将走 3 步。 从 (3,1) 出发将…

基于基于微信小程序的社区订餐系统

作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…

ElasticSearch备考 -- Async search

一、题目 通过异步方式查询earthquakes索引下Magnitude大于5的数据 二、思考 正常的查询大家可能会用的多一点,这种异步查询为数据量比较大的查询在后台执行,不用同步等待结果,待执行完成在获取结果。 三、解题 Step 1、准备基础数据 # D…

Sping源码:三级缓存

目录 一、概念1、三级缓存的作用2、循环依赖的含义 二、代码1、代码下载2、文件功能介绍3、源码分析3.1、找到获取A对象的位置,打断点进行debug操作3.2、一步步找到在A对象中注入B对象的位置3.3、一步步找到B对象注入A对象的位置3.4、往下找到通过三级缓存解决循环依…

YouTube音视频合并批处理基于 FFmpeg的

专门针对YouTube高品质分享处理的,将音频和视频合并。 首先下载ffmpeg.exe网上随便下载。 echo off title YouTube 音视频合并 20241004 echo 作者:xiaoshen echo 网站:http://www.xiaoshen.cn/ echo. set /p audio请将【音频】文件拖拽到此…

六、Java 基础语法(下)

一、变量 1、变量的定义与使用 变量就是内存中的存储空间,空间中存储着经常发生改变的数据变量定义格式: 数据类型 变量名 数据值使用时根据变量名使用举例如下,上面是代码,下面是输出 2、变量的注意事项 变量名不允许重复…

Vue入门-指令学习-v-show和v-if

v-show: 作用:控制元素的显示隐藏 语法:v-show"表达式" 表达式值true显示,false隐藏 v-if 作用:控制元素的显示隐藏(条件渲染) 语法: vif"表达式" 表达式tr…

字节跳动收购Oladance耳机:强化音频技术,加速VR/AR生态布局

字节跳动收购Oladance耳机:加码VR/AR领域布局 近日,字节跳动宣布已完成对开放式耳机品牌Oladance的收购,实现了对该品牌的100%控股。这一收购标志着字节跳动在AI硬件领域的进一步扩展和深化,特别是对其VR/AR领域布局的重要加码。 …

STM32使用Keil5 在运行过程中不复位进入调试模式

一、选择Options for Target进入设置 二、选择所使用的调试器,这里以ST-Link为例。取消勾选Load Application at Startup 可以在进入调试模式的时候不会从新加载程序!从而不破坏现场 三、点击Setting进入 四、取消勾选Reset after Connect 使得调试器连接…

DotNetty ChannelRead接收数据为null

问题:C#使用Dotnetty和Java netty服务器通讯,结果能正确发送数据到服务器,却始终接收不到服务器返回的数据。 解决:一定一定要注意服务器和客户端使用的编码一定要完全一样才行 我先前在客户端添加了StringDecoder,服务器却没有…

malloc源码分析之 ----- 你想要啥chunk

文章目录 malloc源码分析之 ----- 你想要啥chunktcachefastbinsmall binunsorted binbin处理top malloc源码分析之 ----- 你想要啥chunk tcache malloc源码,这里以glibc-2.29为例: void * __libc_malloc (size_t bytes) {mstate ar_ptr;void *victim;vo…

Windows安装Linux子系统报错:WslRegisterDistribution failed with error: 0x8007019e

WslRegisterDistribution failed with error: 0x8007019e 报错截图如下图: 该处是由于没有安装Linux内核,因此需要安装。可前往官网查看详情:https://aka.ms/wslinstall 需要解决该问题,可参照官网方法(我没试过官网…

【优选算法之队列+宽搜/优先级队列】No.14--- 经典队列+宽搜/优先级队列算法

文章目录 前言一、队列宽搜示例:1.1 N 叉树的层序遍历1.2 ⼆叉树的锯⻮形层序遍历1.3 ⼆叉树最⼤宽度1.4 在每个树⾏中找最⼤值 二、优先级队列(堆)示例:2.1 最后⼀块⽯头的重量2.2 数据流中的第 K ⼤元素2.3 前 K 个⾼频单词2.4 …

Android车载——VehicleHal初始化(Android 11)

1 概述 VehicleHal是AOSP中车辆服务相关的hal层服务。它主要定义了与汽车硬件交互的标准化接口和属性管理,是一个独立的进程。 2 进程启动 VehicleHal相关代码在源码树中的hardware/interfaces/automotive目录下 首先看下Android.bp文件: cc_binary …

Maven的生命周期与依赖作用域介绍

说明:本文介绍Maven的生命周期,以及在pom.xml文件中每个依赖(dependency标签内)scope标签的内容。 Maven生命周期 在IDEA项目中,右侧边栏,点Maven,可以看到以下生命周期。 其中, c…

Spring MVC 常用注解

目录 基础概念 常用注解介绍 基础概念 1、MVC :代表一种软件架构设计思想,通俗的理解:客户端发送请求到后台服务器的Controller(C),控制器调用Model(M)来处理业务逻辑,处理完成后,返回处理后的数据到Vie…

Deformable Transformer论文笔记

原文链接 [2010.04159] Deformable DETR: Deformable Transformers for End-to-End Object Detection (arxiv.org)https://arxiv.org/abs/2010.04159 原文笔记 What 作者结合了可变形卷积的稀疏空间采样和 Transformer 的关系建模能力的优点。提出了Deformable Detr Defor…

文心一言 VS 讯飞星火 VS chatgpt (359)-- 算法导论24.3 1题

一、在图 24-2上运行Dijkstra算法,第一次使用结点 s s s作为源结点,第二次使用结点 z z z作为源结点。以类似于图 24-6 的风格,给出每次while循环后的 d d d值和 π π π值,以及集合 S S S中的所有结点。如果要写代码&#xff0c…

CSRF | GET 型 CSRF 漏洞攻击

关注这个漏洞的其他相关笔记:CSRF 漏洞 - 学习手册-CSDN博客 0x01:GET 型 CSRF 漏洞攻击 —— 理论篇 GET 型 CSRF 漏洞是指攻击者通过构造恶意的 HTTP GET 请求,利用用户的登录状态,在用户不知情的情况下,诱使浏览器…

PCIe配置篇(1)——如何进行配置操作(一)

一、功能的唯一标识——BDF 首先我们简单回顾一下总线(Bus)、设备(Device)、功能(Function)这几个概念: 功能(function):是PCI设备中独立的功能单元&#xff…