JDBC的增删改查

news2025/1/18 13:55:53

文章目录

  • 前言
  • 创建数据库
  • 基础版
    • JDBC实例添加
    • JDBC实例删除
    • JDBC实例修改
    • JDBC实例查询
  • 高级版
    • JDBC实例添加
    • JDBC实例删除
    • JDBC实例修改
    • JDBC实例查询


前言

JDBC编程步骤:

  1. 加载数据库驱动程序
  2. 创建数据库连接对象
  3. 创建Statement语句对象(createStatement、prepareStatement)
  4. 执行SQL语句
  5. 处理结果集(只有查询需要)
  6. 释放资源

JDBC 的主要作用是连接 Java 数据库连接,使用它可以在Java程序中执行数据库的SQL语句

JDBC 是由 Java 语言定义接口和数据库厂商提供实现类组成。

用到的接口有:
Connection:特定数据库的连接,在连接上下文中执行SQL语句并返回结果。
Statement:用于执行静态SQL语句并返回它所生成结果的对象。
PreparedStatement:表示预编译的SQL语句的对象,继承并扩展了Statement接口。
ResultSet:装载数据库结果集的接口。

在这里插入图片描述

创建数据库

提示:下面所有代码的实现都是基于此数据库

CREATE TABLE user (
  id int(4) PRIMARY KEY auto_increment, -- 用户ID 主键 不需要强调非空
  name varchar(20) NOT NULL,   -- 用户姓名 非空
  email varchar(50) NOT NULL UNIQUE,  -- 用户邮箱 非空 唯一
  phone varchar(20) NOT NULL UNIQUE,  -- 用户电话 非空 唯一
  birth date NOT NULL  -- 用户生日 非空
);

在上面创建语句中,约束应该大写,因此 PRIMARY KEY、NOT NULL、UNIQUE 应该全部大写。

在Eclipse中新建Java项目,然后新建文件夹取名lib,放入jar包

在这里插入图片描述

以下是MySQL8版本的代码

随后右键放入的jar包,选择构建路径→添加至配置路径

在这里插入图片描述
选择完后就会看到多一个引用的库在这里插入图片描述
随后新建src新建包和类

基础版

JDBC实例添加

//所有导入的包都是java.sql的
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class InsertDemo {
	public static void main(String[] args) throws Exception {
		//JDBC编程步骤
		//1、加载数据库驱动程序
		Class.forName("com.mysql.cj.jdbc.Driver");
		//2、创建数据库连接对象
		//传入三个参数 数据库的URL、用户名、密码
		//每种数据库驱动程序的名字和数据库URL的写法都不同
		Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/user?characterEncoding=utf8&serverTimezone=Asia/Shanghai","root","123456");
		
		System.out.println(connection);
		//3、创建Statement语句对象
		Statement statement = connection.createStatement();
		//4.执行SQL语句
		//如果执行的是增加 删除 修改语句 ,调用exceuteUpdate,返回值是整数,代表的是影响数据库的行的数量
		//如果执行的是查询语句,调用的是executeQuery 返回值是结果集
		int rows = statement.executeUpdate("insert into user values(4,'赵六','124502@qq.com','12781200101','2019-08-11')"); 
		System.out.println(rows);  //rows拿到影响数据库的行数
		//5、处理结果集
		//插入语句不需要
		//6、释放资源
		//连接、语句、结果集需要释放,调用close方法,先创建的后释放
		statement.close();
		connection.close();		
	}
}

运行结果:

在这里插入图片描述
Navicat中的显示:
以此类推我们改个id和其他几个字段数据,多添加几条

在这里插入图片描述

JDBC实例删除

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class DeleteDemo {
	public static void main(String[] args) throws Exception {
		//1、加载数据库驱动程序
		Class.forName("com.mysql.cj.jdbc.Driver");
		//2、创建数据库连接对象
		Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/user?characterEncoding=utf8&serverTimezone=Asia/Shanghai","root","123456");
		//3、创建Statement语句对象
		Statement statement = connection.createStatement();
		//4、执行SQL语句
		int rows = statement.executeUpdate("delete from user where id=1");  //删除id是1的数据
		System.out.println(rows);
		//5、处理结果集,这里没有
		//6、释放资源
		statement.close();
		connection.close();
	}

}

运行结果
在这里插入图片描述

删到最后控制台就是0了

JDBC实例修改

修改按照上述方法也可以改,但我们接下来换个方法,给他封装一下
把第一步和第二步、第六步封装一下

接下来定义一个JDBC的工具类封装一下
这里是新建了一个包和类

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class JdbcUtil {
//加载驱动程序和创建数据库连接,封装到一个静态代码方法里
public static Connection createConnection() {
		
		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
			//这里不再抛出异常,而是包围它
		} catch (ClassNotFoundException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		Connection connection = null;
		try {
			connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/user?characterEncoding=utf8&serverTimezone=Asia/Shanghai","root","123456");
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		
		return connection;
	}
	
	//释放资源,封装到静态方法中,方便调用
	public static void close(Statement statement,Connection connection) {
		try {
			statement.close();
			connection.close();
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
	}	
}

回到之前的包,新建修改类

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

import com.jdbc.work.util.JdbcUtil;

public class UpdateDemo {
public static void main(String[] args) {
		
		Connection connection = null;
		Statement statement = null;
		//刚才封装到了静态方法里面,这里直接调用
		connection = JdbcUtil.createConnection();
		try {
			statement=connection.createStatement(); //这里异常也用try...catch
			
			int rows = statement.executeUpdate("update user set name='王朝',email='74123@163.com' where id=2");  //修改编号为2的用户姓名与邮箱
		System.out.println(rows);
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}finally {
			JdbcUtil.close(statement, connection);
		}  //释放资源放在finally块里,无论try内代码是否有异常,finally块内代码都会运行
	}
}

在这里插入图片描述

JDBC实例查询

只有查询用到了结果集,我们在JdbcUtil类中再写一个方法,把结果集加进去

	public static void close(ResultSet resultSet,Statement statement,Connection connection) {
		//重载
		try {
			resultSet.close();
			statement.close();
			connection.close();
		} catch (SQLException e) {
			// 包围方式 自动生成的 catch 块
			e.printStackTrace();
		}
	}

下面代码是查询方法

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;

import com.jdbc.work.util.JdbcUtil;

public class QueryDemo {
	public static void main(String[] args) {
		Connection connection = null; //连接
		Statement statement = null; //语句
		ResultSet resultSet = null;	//结果集,只有查询需要
		
		connection = JdbcUtil.createConnection();  //创建连接
		try {
			statement = connection.createStatement();
			resultSet = statement.executeQuery(" select * from user ");
			//5.处理结果集
			//处理结果集其实就是从结果集中将数据取出使用
			//使用while循环语句  次数不固定,先判断
			//结果集next方法判断是否有数据行
			while(resultSet.next()) {
				//查询语句中查询几列就需要取出几列数据
				//取数据调用结果集中的getXXX方法
				//数据库中列是整数类型 --- getInt
				//数据库中列是浮点数类型 float double decimal--- getDouble
				//数据库中是日期类型 ---- getDate
				//数据库中是字符型 char varchar ---getString
				int id = resultSet.getInt("id"); //1:第几个数据.最好放列名
				String name = resultSet.getString("name");
				String email = resultSet.getString("email");
				String phone = resultSet.getString("phone");
				Date birth = resultSet.getDate("birth");
				
				System.out.println(id+"\t"+name+"\t"+email+"\t"+phone+"\t"+birth);				
			}
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}finally {
			JdbcUtil.close(resultSet,statement, connection);
		}
		
	}

}

控制台结果:
在这里插入图片描述

高级版

上面的数据是写在代码内的,但是我们应该让他是个变量
这里用到了prepareStatement它是Statement子接口,预编译语句
因为Statement会引起SQL注入问题,同时变量的拼接很不方便

JDBC实例添加

第一种方法:

所用到的方法均作为笔记写在了注释内

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
import com.jdbc.work.util.JdbcUtil;

public class InsertDemo {
	public static void main(String[] args) {
		Connection connection = null;
		PreparedStatement preparedStatement = null;
		//它是Statement子接口,预编译语句
		//Statement会引起SQL注入问题,同时变量的拼接很不方便
		
		connection = JdbcUtil.createConnection();
		//调用prepareStatement方法创建预编译语句对象
		//传入执行的SQL语句,SQL语句中的数据部分替换成?
		try {
			preparedStatement = connection.prepareStatement("insert into user values(?,?,?,?,?)");
			//预编译语句执行前,必须给所有?赋值
			//调用PreparedStatement(预编译)语句中的setXXX方法,类似于结果集中的getXXX对应
			Scanner scanner = new Scanner(System.in);
			int id;
			String name;
			String email;
			String phone;
			String birth;
			
			System.out.println("请输入用户id");
			id = scanner.nextInt();
			
			System.out.println("请输入用户姓名");
			name = scanner.next();
			
			System.out.println("请输入用户邮箱");
			email = scanner.next();
			
			System.out.println("请输入用户电话");
			phone = scanner.next();
			
			System.out.println("请输入用户生日");
			birth = scanner.next(); //需要转换,现在是字符串
			//调用setXXX方法,从左向右方向依次给?赋值
			preparedStatement.setInt(1, id);
			//赋值时问号的序号从1开始,数据库是个特例
			preparedStatement.setString(2, name);
			preparedStatement.setString(3, email);
			preparedStatement.setString(4, phone);
			
			//类型转换 把date类型转换成String类型
			//1.将String类型转换成java.util.Date类型 
			SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); 
			Date d1 = sdf.parse(birth);  //倒包:java.util
		    //2.将java.util.Date类型转换成java.sql.Date 
			java.sql.Date d2 = new java.sql.Date(d1.getTime()); //完整包名加上
			
			preparedStatement.setDate(5, d2);
			//预编译执行和普通语句执行的方法一致
			//执行时不需要再次指定SQL语句
			int rows = preparedStatement.executeUpdate();
			System.out.println(rows);
		} catch (Exception e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}finally {
			JdbcUtil.close(preparedStatement, connection);
		}
	}

}

输出结果:
运行时在控制台实现
在这里插入图片描述


第二种方法:

根据上面增加的例子我们可以看到date类型转换需要两步,比较麻烦
应该把转换代码封装一下,方便使用

我们依旧在JdbcUtil类中封装

	//String类型转换为java.sql.Data类型封装到一个方法里
	public static java.sql.Date toSqlDate(String string){
		java.util.Date d1 = null;
		java.sql.Date  d2 = null;
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		try {
			d1 = sdf.parse(string);
			d2 = new java.sql.Date(d1.getTime());  //try...catch后写第二次转换
		} catch (ParseException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}

		return d2;  //转换后结果的返回
	}

那现在上面写的InsertDemo(添加)内的转换代码就不需要了,可以删除
第五条preparedStatement方法需要调用一下方法,拿到转换后的SqlDate,把birth字符串传进去:

preparedStatement.setDate(5, JdbcUtil.toSqlDate(birth));

另外,在JdbcUtil内的加载驱动程序代码在实际运行中只运行了一次
在方法前面加上静态代码块,静态代码块的代码在程序中只会运行一次,所以把try…catch内的代码放在static静态代码块中
请添加图片描述

最后JdbcUtil类中代码为:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.ParseException;
import java.text.SimpleDateFormat;

public class JdbcUtil {
	static {
		try {
			Class.forName("com.mysql.cj.jdbc.Driver");
			//这里不再抛出异常,而是包围它
		} catch (ClassNotFoundException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
	}
//加载驱动程序和创建数据库连接,封装到一个静态代码方法里
public static Connection createConnection() {
		
		Connection connection = null;
		try {
			connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/user?characterEncoding=utf8&serverTimezone=Asia/Shanghai","root","123456");
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		
		return connection;
	}
	
	//释放资源,封装到静态方法中,方便调用
	public static void close(Statement statement,Connection connection) {
		try {
			statement.close();
			connection.close();
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
	}	
	
	public static void close(ResultSet resultSet,Statement statement,Connection connection) {
		//重载
		try {
			resultSet.close();
			statement.close();
			connection.close();
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
	}

	//String类型转换为java.sql.Data类型封装到一个方法里
	public static java.sql.Date toSqlDate(String string){
		java.util.Date d1 = null;
		java.sql.Date  d2 = null;
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		try {
			d1 = sdf.parse(string);
			d2 = new java.sql.Date(d1.getTime());
		} catch (ParseException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}

		return d2;
	}

}

再次运行添加
在这里插入图片描述

JDBC实例删除

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

import com.jdbc.work.util.JdbcUtil;

public class DeleteDemo {
	public static void main(String[] args) {
		Connection connection = null;
		PreparedStatement preparedStatement = null;
		Scanner scanner = new Scanner(System.in);
		
		connection = JdbcUtil.createConnection();
		try {
			preparedStatement = connection.prepareStatement("delete from user where id=?");
			System.out.println("请输入删除的用户id");
			int id = scanner.nextInt();
			preparedStatement.setInt(1, id);
			int rows = preparedStatement.executeUpdate();
			System.out.println(rows);
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		} finally {
			JdbcUtil.close(preparedStatement, connection);
		}
		
	}

}

运行结果
在这里插入图片描述

JDBC实例修改

根据ID值改其他条件

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

import com.jdbc.work.util.JdbcUtil;

public class UpdateDemo {
	public static void main(String[] args) {
		Connection connection = null;
		PreparedStatement preparedStatement = null;
		Scanner scanner = new Scanner(System.in);

		connection = JdbcUtil.createConnection();
		try {
			preparedStatement = connection.prepareStatement("update user set name = ?,email=?,phone=?,birth=? where id=?");
			int id,age;
			String name,birth,pwd;

			System.out.println("请输入需要修改的用户id");
			id = scanner.nextInt();
			
			System.out.println("请输入修改后的用户名");
			name = scanner.next();
			
			System.out.println("请输入修改后的用户邮箱");
			String email = scanner.next();
			
			System.out.println("请输入修改后的用户电话");
			String phone = scanner.next();
			
			System.out.println("请输入修改后的用户生日");
			birth = scanner.next();
			
			preparedStatement.setString(1, name);
			preparedStatement.setString(2, email);
			preparedStatement.setString(3, phone);
			preparedStatement.setDate(4, JdbcUtil.toSqlDate(birth));
			preparedStatement.setInt(5, id);
			int rows = preparedStatement.executeUpdate();
			System.out.println(rows);
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}finally {
			JdbcUtil.close(preparedStatement, connection);
		}

	}

}

输出结果:
在这里插入图片描述

JDBC实例查询

模糊查询

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Scanner;

import com.jdbc.work.util.JdbcUtil;

public class QueryDemo {
	public static void main(String[] args) {
		Connection connection = null;
		PreparedStatement preparedStatement = null;
		ResultSet resultSet = null;
		Scanner scanner = new Scanner(System.in);
		
		connection = JdbcUtil.createConnection();
		try {
			preparedStatement = connection.prepareStatement("select * from user where name like ?");
			System.out.println("请输入查询的用户名(支持模糊查询)");
			String name = scanner.next();
			preparedStatement.setString(1, "%"+name+"%");
			resultSet = preparedStatement.executeQuery();
			//处理结果集
			while(resultSet.next()) {
				int id = resultSet.getInt("id");
				name = resultSet.getString("name");
				String email = resultSet.getString("email");
				String phone = resultSet.getString("phone");
				Date birth = resultSet.getDate("birth"); 
				System.out.println(id+"\t"+name+"\t"+email+"\t"+phone+"\t"+birth);
			}
			
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}finally {
			JdbcUtil.close(resultSet, preparedStatement, connection);
		}
	}
	
}

这里为了输出美观,已提前在Navicat内更改了数据

输入要查询的数据:
在这里插入图片描述

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

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

相关文章

谈谈聚簇索引与非聚簇索引

技术主题 聚簇索引是一种数据的存储方式,它的数据行只存放在索引(B+树)的叶子上,内部节点不存放数据。 聚簇索引 聚簇索引默认是主键,如果没有定义主键,innodb会选择一个唯一的非空索引代替。如果没有这种索引,innodb会隐式定义一个主键作为聚簇索引。 非聚簇索引 非…

百度出品,Nature重磅 -- 优化的mRNA设计算法可改善mRNA的稳定性和免疫原性

摘要 尽管mRNA疫苗已用于COVID-19的预防,但仍然面临不稳定和易降解的风险,这是mRNA疫苗存储、配送、效价等面临的重要障碍。先前的研究已表明,增加二级结构可延长mRNA的半衰期,再加上选择优化的密码子,可改善蛋白表达。…

Django实现接口自动化平台(五)httprunner(2.x)基本使用【持续更新中】

上一章: Django实现接口自动化平台(四)解决跨域问题【持续更新中】_做测试的喵酱的博客-CSDN博客 下一章: 一、参考地址: 使用说明_httprunner2.0 概述及使用说明 二、介绍 HttpRunner是一款面向 HTTP(S) 协议的通…

一文带你了解MySQL之锁

目录 一、解决并发事务带来问题的两种基本方式1.1 一致性读(Consistent Reads)1.2 锁定读(Locking Reads)1.2.1 共享锁和独占锁1.2.2 锁定读的语句 1.3 写操作 二、多粒度锁三、MySQL中的行锁和表锁3.1 其他存储引擎中的锁3.2 Inn…

高通KMD框架详解

和你一起终身学习,这里是程序员Android 经典好文推荐,通过阅读本文,您将收获以下知识点: 一、概览二、核心模块解析三、模块初始化四、处理UMD CSL请求 一、概览 利用了V4L2可扩展这一特性,高通在相机驱动部分实现了自有的一套KMD…

未来3年,请善待你的工作

作者| Mr.K 编辑| Emma 来源| 技术领导力(ID:jishulingdaoli) “如果不是现在环境差,下家不好找,我早TM跟那个傻X老板翻桌子走人了,这破公司我真是一天都不想待…”这是一位粉丝朋友给K哥私信中的一段话。类似同款的话&#xff…

百度推出基于大模型的代码编写助手“Comate”真的好用吗?

‍ 点击蓝字 关注我们 关注并星标 从此不迷路 计算机视觉研究院 公众号ID|计算机视觉研究院 学习群|扫码在主页获取加入方式 计算机视觉研究院专栏 Column of Computer Vision Institute 6月6日,在文心大模型技术交流会(成都&…

从业务出发,K8S环境自建和非自建整体架构设计比较

新钛云服已累计为您分享751篇技术干货 随着数字化转型的大潮到来,越来越多的企业开始上云,同时也纷纷加入到微服务和K8S队伍中。但在K8S整体环境究竟应该用自建的还是非自建?以及他们需要用到的服务,究竟应该自建还是直接用PAAS服…

02.加载GDT表,进入保护模式

加载GDT表,进入保护模式 加载GDT表,实现操作系统从实模式进入保护模式 参考 操作系统学习 — 启动操作系统:进入保护模式 保护模式与实模式 GDT、GDTR、LDT、LDTR 调用门与特权级 趣谈 Linux 操作系统 在01.硬盘启动盘,加载操作系…

要能力、要稳定也要降本——百度多媒体技术回顾

摘要:多媒体技术生态进入到存量市场,客户既要又要还要成为常态。如何将能力、质量与稳定性、成本不断优化,就是各个多媒体技术平台的必修课。本文以百度智能视频云为例,纵览了其在RTC、边缘计算、视频编码等关键能力与用户体验和成…

腾讯搜索的系统架构是如何达到99.994%高可用的?

👉腾小云导读 本文主要是搜索在稳定性治理实践的经验总结,讲述了搜狗搜索在技术债治理基础上如何将可用性提升一个量级,事故级 MTTD(平均故障检测时间)、MTTR(平均响应时间)优化一个量级&#x…

chatgpt赋能python:Python的IDLE运行方式

Python的IDLE运行方式 Python是一种非常流行的编程语言,其优雅简洁的语法和丰富的库资源,使得Python在很多领域都得到广泛应用。在Python的开发过程中,IDLE是一种常用的Python集成开发环境(IDE),对于初学者…

关于操作系统调度器的三篇论文

【引子】没有忘记,目前从事的是DingOS 操作系统相关工作,没有因为LLM 而迷失。LLM 会成为基础设施,LLM 会为操作系统赋能,但是操作系统的价值是客观存在的,除非,计算机体系结构发生了翻天覆地的变化。 在任…

Java面试都只是背答案吗

Java 八股文面试当然要背,不背很难通过面试的 Java基础 Java基础面试题 Java的特点Java 与 C 的区别JDK/JRE/JVM三者的关系Java程序是编译执行还是解释执行?面向对象和面向过程的区别?面向对象有哪些特性?数组到底是不是对象&a…

编写Python程序求数组中最长的字符串

点击上方“Python爬虫与数据挖掘”,进行关注 回复“书籍”即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 移船相近邀相见,添酒回灯重开宴。 大家好,我是皮皮。 一、前言 前几天在Python白银群【王子】问了一个Python基础的问题&#x…

Ubuntu离线安装docker与nvidia-docker

Ubuntu离线安装docker与nvidia-docker 安装 docker 20.10.17安装 nvidia-docker 和 nvidia-container-toolkit docker与nvidia-docker离线安装包 安装 docker 20.10.17 查看Ubuntu操作系统版本的详细信息,不同的版本所依赖的deb不同。 lsb_release -aCodename为&a…

一文带你读懂:TCP连接的三次握手和四次挥手(上篇)

TCP 是面向连接的协议,所以使用 TCP 前必须先建立连接,而建立连接是通过三次握手来进行的。 天下没有不散的宴席,对于 TCP 连接也是这样, TCP 断开连接是通过四次挥手方式。 下面我们通过实操,来彻底理解三次握手和四次…

linux ubi文件系统更新失败问题分析2

昨天打包了一个ubi根文件系统,打包成功,写板子flash成功,但系统运行后还是老的文件系统,具体过程如下: 使用脚本1,打包rootfs系统: 打包后的文件系统,下载到板子后,查看…

01_MySQL索引简介

影响性能下降、SQL慢体现在:执行时间长或者等待时间长 影响sql性能的常见情况: 数据过多:分库分表(根据微服务划分库、按照地域或时间分表存储、按照数据的特定字段对分库数量求余)关联了太多的表,太多join:允许表出现…

在口袋妖怪世界中理解ChatGPT的思维

深度学习自然语言处理 原创作者:Winni 今天为大家分享一篇研究,当ChatGPT穿越到口袋妖怪世界,是否会理解并应用这个虚构世界的知识呢? 熟悉口袋妖怪的朋友们一定知道,这些可爱的生物们有着各种不同的属性、类别和技能。…