JDBC编程(Mysql)

news2024/11/24 22:51:42

目录

1.什么是jdbc

2.使用

2.1下载mysql数据库驱动

2.2导入项目

2.3编写代码

2.3.1数据源

2.3.2和数据库服务器建立连接

2.3.3构建一个操作数据库的sql语句

2.3.4执行sql

2.3.5释放前面创建的各种资源

2.3.6运行java程序

2.4其他操作

2.4.1修改操作

2.4.2删除操作

2.4.3查询操作

感谢您的访问!!


在学习完mysql数据库后,学习使用java来操作数据库尤为重要,这篇文章为大家介绍jdbc编程基础


1.什么是jdbc

实际上在我们日常开发中,手动直接操作数据库的情况是比较少的(测试数据,定位bug之类的),更多的是通过java等业务代码来操作

在java中,是通过jdbc这样的技术来操作mysql的

这是因为mysql的底层是c/c++实现的数据库,本身也提供了一些api供程序员调用,从而操控数据库

什么是api?

api,全名是 Application programming interface,即应用程序编程接口,这是一个通用的概念,而不仅仅是局限在java里面.

我们可以把这个词理解成"一组类"或者"一组方法",这都是别人已经写好的,现成的,可以直接调用,就可以实现一些效果

其中,对于java来说,java提供了:标准库,只要你安装了java,就能使用标准库里面的类和方法,即标准库里面的api

但是我们也可以使用其他大佬写好的类和方法,即第三方的库

当然在其他的编程语言也同样有自己的库,也能使用第三方的api

有的库,提供的api特别多,就现成了一个体系,这种情况,也可以称为"SDK"(软件开发工具包),java中的sdk就是jdk

而不仅仅是mysql,其他的数据库比如oracle,sql server.sqlite...都提供了这样的api供程序员调用

但是这样就会出现一个问题:

不同的数据库提供的api是不同的,虽然提供的功能大同小异,但是细节上差异还是非常大的.这样程序员学习的成本就会很高

这时java就提供了一套api标准接口,就让不同的数据库都按照java提供的api适配过来,就是让每个数据库都额外写一些代码,能够按照java提供的这一套标准把原来的原生api重新封装一下.后续程序员在使用的时候,只需要掌握java提供的这套api,就能适配到其他数据库了

那么这一套api就是jdbc

其中,像这样的接口转化程序,被称为"数据库驱动"

JDBC是java标准库提供的,只要安装了jdk就能使用,但是jdbc要想操作数据库就要下载并导入mysql的驱动包

这个.jar文件,实际上就是类似于.rar一样的压缩包文件,这里包含了许多.class这样的文件(.java编译出来的字节码文件)

写好的java文件,就可以把编译出来的.class文件拷贝给别人,别人就能正常运行使用了

但是一个程序中往往会有很多.class文件,涉及很多复杂度目录结构,直接拷贝一堆.class文件不太好

于是就约定把这些要发布的.class文件按照特定格式打包压缩,就得到了.jar文件,后续直接拷贝.jar文件即可.并且jvm可以识别.jar文件的内部的.class文件并直接运行

.jar文件是最常见的一种发布java程序的方式


2.使用

2.1下载mysql数据库驱动

直接去中央仓库下载即可:https://mvnrepository.com/

由于我用的是mysql5.7,那么这里就下载旧版本即可

往下拉就会看到适配5版本的驱动:

点击即可下载

但是我们会看到下面有个警告:

漏洞!!但是对于我们自己的数据库实际上没啥关系

直接下载即可

2.2导入项目

在java项目中随便创建一个目录

将刚刚下载的驱动放到里面去

此时我们要右键这个目录:

这样的操作是告诉idea,当前这个目录是存放第三方的目录,此时idea就能够识别到我们拷贝进来的驱动包了

这样刚刚的驱动就能直接展开了

上述就是jdbc程序的准备工作,那么接下载我们就可以编写代码了

2.3编写代码

要想编写jdbc,还需要准备好数据库和数据表(虽然jdbc也能进行建表操作,但是一般都是在数据库中就已经创建好的)

2.3.1数据源

即要操作的数据库,数据是在哪里

那么在mysql中就要设置好访问数据库的名字,访问数据库的用户名和密码

但是这个dataSourse是jdbc自带的接口,但是接口是不能new实例的

这个类就来自于mysql的驱动包

这个过程就类似:数据库厂商和jdbc进行对接,就是让数据库厂商实现jdbc中提供的一些接口,进一步实现其中约定好的抽象方法

但是实际上:

 MysqlDataSource mysqlDataSource = new MysqlDataSource();

也是可以的

但是更多的是第一种写法,因为这便于代码和数据库之间的"解耦合"

万一未来有一天需要变更数据库,第一种代码的写法,改动成本就低一点,即后续使用数据源的时候,看到的都是dataSourse类型,至于里面实际上的数据库是什么就不知道了,这样更加便于切换数据库,反之,如果采用mysqlDataSourse这种写法,就可能会经常涉及到MysqlSourse这样的概念,就会使得后续的修改更加复杂

这时候通过url连接到mysql数据库,就要向下转型回来了

其中这里的url是:唯一资源定位符,我们的客户端要通过网络访问到数据库服务器进行操作,那么url就描述了服务器/服务器上的资源在网络中所在的位置

((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/j20240228?charsetEncoding=utf8&useSSL=false");

URl:协议的名称://ip地址:端口号/数据库名?参数=值&参数=值

实际上这一串不需要背下来,后续需要直接拷贝即可

实际上mysql可以手动创建各种数据库用户名,默认会带一个root用户(指的是一个管理员账户(权限最大))

下面的密码就是你的数据库密码

这里为什么要向下转型回来??

因为dataSourse是要能够对接到不同的数据库的,而不同的数据库实际上设置数据源的方式是不一样的,对于mysql是url,user,password,但是对于其他的就不一定了

2.3.2和数据库服务器建立连接

进行客户端-服务器之间的通信的时候,常见的有两种通信方式

(1)有连接(jdbc就属于有连接):类似于打电话,拨号后需要对方接听

(2)无连接:类似于发短信

 Connection connection = dataSource.getConnection();

需要声明异常

注意:这里的connection要选择sql的,

那么这个Connection对象,就表示客户端与服务器之间的:连接对象

但是实际上在getConnection是很可能失败的(服务器没有接受连接)

原因包括但是不限于:

(1)数据库服务器没有正常启动

(2)url写错了

(3)用户名写错了

(4)密码写错了

(5)网络断开了

....

2.3.3构建一个操作数据库的sql语句

虽然是通过java来操作数据库,但是实际上核心还是sql,只不过把sql嵌套在java中

  String sql = "insert into jdbctest values(1,'张三')";

此时还需要一个语句对象

有这两种方式

第一个仅仅是代表一个普通的语句对象,但是第二个则是一个带有"预编译"功能的语句对象

把一个字符串的sql发生到数据库服务器上,是先要对sql进行解析以及各种校验(判定sql是否符合语法要求等),而这样的操作是需要一定开销的,虽然这个开销不大,但是一个数据库服务器往往是要同时给多个客户端提供服务的

因此为了减轻数据库服务器的负担,就可以在客户端这边完成检验

  //语句对象
         PreparedStatement preparedStatement = connection.prepareStatement(sql);
2.3.4执行sql

把刚刚解析好sql语句发生给数据服务器进行操作了

实际上偶遇两种方式:

对于insert,updata.delete统一都是executeUpdate,而selet就是executeQuery

我们这里先进行插入操作

 int n = preparedStatement.executeUpdate();

这里的返回值是一个int类型,表示这个操作影响了几行数据

通过执行这个方法,就会在内部给数据库服务器发起请求,请求中就是包含解析后的sql,等待数据库执行sql,过一会执行完后数据库返回响应,这个方法再获取响应,通过返回值的方式体现出来

2.3.5释放前面创建的各种资源

主要是释放语句对象和连接对象,注意:dataSourse是不必释放的

在java中有垃圾回收机制(GC),可以自动帮我们回收我们不用的内存

但在编程过程中涉及到的有限资源不仅仅是内存

如果是内存,那么GC自动回收

但如果是其他资源,java无能为力,就需要手动释放了

注意这里的释放顺序,要确保先创建的后释放

2.3.6运行java程序

但是在这里,当前插入的内容是在代码中写死的

如果想要插入不同的数据就需要修改代码重新编译,但是很多时候是需要在程序运行的时候让用户自己插入数据的

拼接字符串

 int id = scanner.nextInt();
         String name = scanner.nextLine();
         String sql = "insert into jdbctest values(" + id + ",'" + name + "')";
         //语句对象
         PreparedStatement preparedStatement = connection.prepareStatement(sql);

这样就能完成预期效果了

但是实际上这种方式不可行

首先可读性非常差,很容易拼错;其次也不太安全,可能会引起sql注入攻击这样的漏洞

还是比较推荐使用prepareStatement提供的api来完成动态内容的设置

 
 int id = scanner.nextInt();
         String name = scanner.nextLine();
         String sql = "insert into jdbctest values(?,?)";
         //语句对象
         PreparedStatement preparedStatement = connection.prepareStatement(sql);
         preparedStatement.setInt(1,id);//表示第一个问号
         preparedStatement.setString(2,name);

这种方式jdbc内部会进行校验,避免上述危险操作

2.4其他操作
2.4.1修改操作
 
public static void main(String[] args) throws SQLException {
         Scanner scanner = new Scanner(System.in);
         //数据源
         DataSource dataSource = new MysqlDataSource();
         ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/j20240228?charsetEncoding=utf8&useSSL=false");
         ((MysqlDataSource)dataSource).setUser("root");
         ((MysqlDataSource)dataSource).setPassword("2222");
 ​
         //建立联系
         Connection connection =  dataSource.getConnection();
 ​
         //构造sql
         int id = scanner.nextInt();
         String name = scanner.nextLine();
         String sql = "update JDBCTest set name = ? where id = ?";
         PreparedStatement statement = connection.prepareStatement(sql);
         statement.setInt(2,id);
         statement.setString(1,name);
 ​
         //执行sql
         int n = statement.executeUpdate();
         System.out.println(n);
 ​
         //释放资源
         statement.close();
         connection.close();
     }
2.4.2删除操作
 public static void main(String[] args) throws SQLException {
         Scanner scanner = new Scanner(System.in);
         //数据源
         DataSource dataSource = new MysqlDataSource();
         ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/j20240228?charsetEncoding=utf8&useSSL=false");
         ((MysqlDataSource)dataSource).setUser("root");
         ((MysqlDataSource)dataSource).setPassword("2222");
 ​
         //建立连接
         Connection connection = dataSource.getConnection();
 ​
         //构造sql
         int id = scanner.nextInt();
         String sql = "delete from jdbcTest where id = ?";
         PreparedStatement statement = connection.prepareStatement(sql);
         statement.setInt(1,id);
 ​
         //执行sql
         int n =  statement.executeUpdate();
         System.out.println(n);
 ​
         //释放资源
         statement.close();
         connection.close();
     }
2.4.3查询操作

查询操作又和其他的不太一样

前面的操作都是一样的,但是在执行sql语句的时候

  
//构造sql语句
         String sql = "select * from jdbcTest";
         PreparedStatement statement = connection.prepareStatement(sql);
 ​
         //执行sql语句
         ResultSet resultSet = statement.executeQuery();

这里会返回一个结果集合

我们需要通过resultSet.next来得到里面的数据

 ResultSet resultSet = statement.executeQuery();
         while(resultSet.next()){
             int id = resultSet.getInt("id");
             String name = resultSet.getString("name");
             System.out.println(id);
             System.out.println(name);
         }

这个next就像一个指针,一开始是指向数据的上方,后面会往下走,直到数据遍历完

注意:在最后释放资源的时候,要释放resultSet

 //释放资源
        resultSet.close();
        statement.close();
        connection.close();

    //查询
    public static void main(String[] args) throws SQLException {
        Scanner scanner = new Scanner(System.in);

        //数据源
        DataSource dataSource = new MysqlDataSource();
        ((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/j20240228?charsetEncoding=utf8&useSSL=false");
        ((MysqlDataSource)dataSource).setUser("root");
        ((MysqlDataSource)dataSource).setPassword("051215");

        //建立连接
        Connection connection = dataSource.getConnection();

        //构造sql语句
        String sql = "select * from jdbcTest";
        PreparedStatement statement = connection.prepareStatement(sql);

        //执行sql语句
        ResultSet resultSet = statement.executeQuery();
        while(resultSet.next()){
            int id = resultSet.getInt("id");
            String name = resultSet.getString("name");
            System.out.println(id);
            System.out.println(name);
        }

        //释放资源
        resultSet.close();
        statement.close();
        connection.close();
    }

感谢您的访问!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微信小程序开发学习笔记——3.11完成form评论案例的实现逻辑

>>跟着b站up主“咸虾米_”学习微信小程序开发中,把学习记录存到这方便后续查找。 课程连接:https://www.bilibili.com/video/BV19G4y1K74d?p25&vd_source9b149469177ab5fdc47515e14cf3cf74 一、javascript参考手册——splice https://www.…

Instagram代运营和自营优缺点比较 CloudNEO:您全球社交媒体代运营的综合解决方案

在社交媒体营销中,Instagram作为一种非常受欢迎的平台,已成为企业推广品牌和吸引客户的重要工具。然而,对于企业来说,是选择代运营还是自营Instagram账号呢?让我们来比较一下它们各自的优缺点,并推荐CloudN…

plt保存PDF矢量文件中嵌入可编辑字体(可illustrator编辑)

背景: 用默认 plt.savefig() 保存图片,图中文字是以瞄点保存,而不是以文字格式。在编辑矢量图中,无法调整文字大小和字体。 方法: import matplotlib.pyplot as plt import numpy as np# ------输出的图片为illustr…

C#,动态规划问题中基于单词搜索树(Trie Tree)的单词断句分词( Word Breaker)算法与源代码

1 分词 分词是自然语言处理的基础,分词准确度直接决定了后面的词性标注、句法分析、词向量以及文本分析的质量。英文语句使用空格将单词进行分隔,除了某些特定词,如how many,New York等外,大部分情况下不需要考虑分词问题。但有些情况下,没有空格,则需要好的分词算法。…

2024年嵌入式校招

春招指的是一年中的春季招聘季节,即每年的3月份至5月份,是许多公司和组织开始招聘新毕业生或经验较少的求职者的时间。春招通常是大学生或研究生即将毕业,进入社会工作的重要时期。在这个时期,许多公司会举行一系列的宣讲会、招聘…

【原创】java+swing+mysql二手车交易管理系统

前言: 本文主要介绍了二手车交易管理设计与实现。首先,通过市场需求,我们确定了二手车的功能,通常的二手车交易系统都是B/S架构,然而我们今天要用javaswing去开发一个C/S架构的二手车交易管理系统,主要功能…

llinux C语言在网络编程时使用标准IO

目录 fdopen(3)函数 使用标准IO发送数据 使用标准IO接收数据 注意 先看一个简单的TCP客户端程序&#xff1a; #include <stdio.h> #include <arpa/inet.h> #include <sys/socket.h> #include <stdlib.h> #include <string.h> #include <…

【数据结构和算法初阶(C语言)】队列实操(概念实现+oj题目栈和队列的双向实现以及循环链表难点题目详解!)

目录 1. 队列的概念及结构 2.队列结构存在的意义应用 3.队列实现的结构选择 4.队列实现 5.队列对数据的处理 5.1队列初始化 5.2队尾入数据 5.3队头出数据 5.4获取队列尾部元素 5.5获取队列头部元素 5.6获取队列中元素个数 5.7检测队列是否为空 5.8销毁队列 6.循环队列补充 7.使…

C语言之快速排序

目录 一 简介 二 代码实现 快速排序基本原理&#xff1a; C语言实现快速排序的核心函数&#xff1a; 三 时空复杂度 A.时间复杂度 B.空间复杂度 C.总结&#xff1a; 一 简介 快速排序是一种高效的、基于分治策略的比较排序算法&#xff0c;由英国计算机科学家C.A.R. H…

矩阵中移动的最大次数

文章目录 所属专栏:BFS算法 题目链接 思路如下&#xff1a; 1.首先我们需要从第一列开始遍历&#xff0c;寻找每一个都能够满足条件的位置&#xff0c;将它插入到数组里面 2.第一列遍历完了后我们先判断第一列的数是否都满足条件插入到数组里面&#xff0c;如果数组为空&#…

03.事件进阶

一、事件流 事件流是对事件执行过程的描述&#xff0c;了解事件的执行过程有助于加深对事件的理解&#xff0c;提升开发实践中对事件运用的灵活度。 如上图所示&#xff0c;任意事件被触发时总会经历两个阶段&#xff1a;【捕获阶段】和【冒泡阶段】。 简言之&#xff0c;捕获…

肝了三天,完成了AIGC工具网站大全,建议收藏再看

说是肝了三天&#xff0c;其实远远不止&#xff0c;前前后后&#xff0c;从资料搜集到最后整理成文&#xff0c;有近一个月了&#xff0c;大家看在整理不易的份上&#xff0c;给点个赞吧&#xff0c;不要光顾着收藏呀&#xff01; 国内网站 AIGC 导航 https://www.aigc.cn 网…

wayland(xdg_wm_base) + egl + opengles 渲染使用纹理贴图的旋转 3D 立方体实例(十三)

文章目录 前言一、使用 stb_image 库加载纹理图片1. 获取 stb_image.h 头文件2. 使用 stb_image.h 中的相关接口加载纹理图片3. 纹理图片——cordeBouee4.jpg二、渲染使用纹理贴图的旋转 3D 立方体1. egl_wayland_texture_cube.c2. Matrix.h 和 Matrix.c3. xdg-shell-client-pr…

使用 pnpm 搭建 monorepo 项目

引言 在我之前的开发经历中&#xff0c;并没有实际使用过 Monorepo 管理项目&#xff0c;尽管之前对此有所了解&#xff0c;但并未深入探究。然而&#xff0c;如今许多开源项目都采纳了 Monorepo 方式&#xff0c;对于不熟悉它的开发者来说&#xff0c;阅读和理解这些项目的源…

关于使用过别人的GitHub/Gitee账号提交东西到仓库后,自己的仓库提交失败问题的解决方法

目录 引言 问题出现的原因 问题的解决方法 打开控制面板 方法一&#xff1a; 方法二&#xff1a; 进入Windows凭据管理器 结语 引言 这个问题折磨了我将近三个小时&#xff0c;为了减少有人和我一样走弯路且防止自己忘记解决方法&#xff0c;便有了这篇文章。 问题出现…

【洛谷 P8602】[蓝桥杯 2013 省 A] 大臣的旅费 题解(图论+深度优先搜索+树的直径+链式前向星)

[蓝桥杯 2013 省 A] 大臣的旅费 题目描述 很久以前&#xff0c;T 王国空前繁荣。为了更好地管理国家&#xff0c;王国修建了大量的快速路&#xff0c;用于连接首都和王国内的各大城市。 为节省经费&#xff0c;T 国的大臣们经过思考&#xff0c;制定了一套优秀的修建方案&am…

uv 必备的工具 ps ai 全家桶合集

非常稀有的资源 &#xff0c;必应搜索 易品资源yipinziyuan 可以找到

浅谈如何自我实现一个消息队列服务器(1)——需求分析

文章目录 一、什么是消息队列&#xff1f;二、当下主流的消息队列(MQ)三、自我实现一个消息队列服务器的前期准备——需求分析3.1 核心概念3.2 broker server 核心概念3.2.1、虚拟主机&#xff08;Virtual Host&#xff09;3.2.2、交换机&#xff08;Exchange&#xff09;3.2.2…

如何构建Docker自定义镜像

说明&#xff1a;平常我们使用Docker运行各种容器&#xff0c;极大地方便了我们对开发应用的使用&#xff0c;如MySQL、Redis&#xff0c;以及各种中间件&#xff0c;使用时只要拉镜像&#xff0c;运行容器即可。本文介绍如何创建一个Demo&#xff0c;自定义构建一个镜像。 开…

基于 K8s 容器集群的容灾架构与方案

作者&#xff1a;庄宇 在设计系统架构时&#xff0c;我们必须假设任何组件和任何基础设施可能会在任何时间失效&#xff0c;例如&#xff1a;自然灾害&#xff0c;电力中断&#xff0c;网络中断&#xff0c;错误的系统变更等。为了应对挑战&#xff0c;我们必须设计合适的容灾…