40. 【Java教程】数据库编程

本小节我们将学习如何使用 Java 语言结合数据库进行编程。注意,学习本小节需要你有一定的 SQL 基础,了解 MySQL 数据库的 基础 CRUD 操作。

本小节我们将选择开源免费的 MySQL 5.7 作为数据库,可以去官网下载并安装 MySQL

通过本小节的学习,你将了解到什么是 JDBC,如何连接数据库,如何关闭数据库,JDBC 的新增、查询、更新和删除接口,如何执行批量等内容。

1. JDBC 概述

1.1 什么是 JDBC

JDBC 就是 Java DataBase Connectivity 的缩写,它是 Java 的标准库,定义了客户端访问数据库的 API。

市面上的数据库有很多种类,连接不同的数据库需要加载不同的数据库驱动。数据库驱动是由厂商提供的,需要我们引入。标准库编写了一套访问数据库的代码,因此不需要标准库代码的改动,只需加载不同的驱动,就可以访问不同的数据库。

1.2 JDBC 的作用

在 JDBC 出现之前,数据库驱动程序由不同的数据库厂商提供,程序员想要操作不同的数据库,就不得不学习各类不同驱动的用法,驱动的学习成本和代码的维护成本都非常高。

Sun 公司发现了这个问题,因此定义了一套标准的访问数据库的 API(即 JDBC),不同厂商按照这个 API 提供的统一接口,实现驱动,这保证了数据库操作的统一性。程序员也不需要再去学习不同厂商提供的五花八门的 API,只需要学习 JDBC 标准 API 即可。代码维护的成本也大大降低。

2. 连接数据库

2.1 建库建表

打开 MySQL 客户端,执行如下 sql 语句:

-- 创建数据库并使用
CREATE DATABASE jdbcdemo;
USE jdbcdemo;-- 创建数据表
CREATE TABLE `user` (`id` int(11) PRIMARY KEY AUTO_INCREMENT,`username` varchar(20) NOT NULL comment "用户名",`nickname` varchar(20) NOT NULL comment "昵称",`password` CHAR(32) NOT NULL comment "密码"
);-- 插入一些数据
insert into `user` values(null, "Colorful", "Colorful3", "123456");
insert into `user` values(null, "mybj123", "小码", "123456");
insert into `user` values(null, "Lillian", "小李", "123456");

2.2 引入驱动

去 maven 中央仓库找到 mysql-connector-java 驱动。如果你熟悉 Maven,可直接引入 maven 依赖:

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.49</version>
</dependency>

如果你还不熟悉 Maven,请跟着我来做如下步骤:

到 maven 中央仓库下载 jar 包,鼠标左键单击 jar

在工程目录下新建一个 lib 包,并将刚刚下载好的 jar 包复制到其中:

在 jar 包上点击右键,选择 Add as Library

如果有弹窗,单击确定即可。此时就可以在你的项目中引入驱动里的类了。

2.3 实例

我们下面通过实例代码来演示 JDBC 的简单使用,以下实例代码有这样几个步骤:

  1. 加载数据库驱动;
  2. 建立连接;
  3. 创建 Statement 对象,用于向数据库发送 SQL 语句;
  4. 获取 ResultSet 对象,取出数据,此对象代表结果集;
  5. 释放资源,断开与数据库的连接。

具体实例如下:

package com.mybj.jdbc;import com.mysql.jdbc.Driver;import java.sql.*;public class JDBCDemo1 {public static void main(String[] args) throws SQLException {// 1. 加载数据库驱动DriverManager.registerDriver(new Driver());// 2. 建立连接final String url = "jdbc:mysql://localhost:3306/jdbcdemo";  // 数据库 urlfinal String user = "root"; // 数据库用户名final String password = "123456"; // 数据库密码Connection connection = DriverManager.getConnection(url, user, password);// 3. 创建 Statement 对象,用于向数据库发送 SQL 语句String sql = "SELECT * FROM `user`";Statement statement = connection.createStatement();ResultSet resultSet = statement.executeQuery(sql);// 4. 获取 ResultSet 对象,取出数据,此对象代表结果集while (resultSet.next()) {int id = resultSet.getInt("id");String username = resultSet.getString("username");String nickname = resultSet.getString("nickname");String pwd = resultSet.getString("password");System.out.println("id=" + id + "; username=" + username + "; nickname=" + nickname + "; password=" + pwd + '\r');}// 5. 释放资源,断开与数据库的连接(调用close()方法)// 5.1 释放 ResultSetresultSet.close();// 5.2 释放 Statementstatement.close();// 5.3 释放 Connectionconnection.close();}
}

运行结果:

id=1; username=Colorful; nickname=Colorful3; password=123456
id=2; username=mybj123; nickname=小码; password=123456
id=3; username=Lillian; nickname=小李; password=123456

看了实例代码,你可能有些晕,这写类都是干嘛的呀?别担心,我们下面就来一一讲解。

4. JDBC 几个类的详解

在上面的实例程序中,我们用到了几个 JDBC 的类:DriverManagerCollectionStatement 和 ResultSet,下面我们将详细介绍这几个类。

4.1 DriverManager

DriverManager 是驱动管理类,此类用于注册驱动和获得连接。

在实际开发中,我们不是像实例这样注册驱动的,我们编写这样地代码会导致驱动注册两次:

// 1. 加载数据库驱动
DriverManager.registerDriver(new Driver());

通过查看 com.mysql.jdbc.Driver 源码,我们发现在静态代码块处已经注册过了驱动:

那么如何改写呢,我们可以使用反射机制来注册驱动:

Class.forName("com.mysql.jdbc.Driver");

加载了 Driver 类,其静态代码块就会执行,因此也就注册了驱动。

除了获得驱动,我们还可以调用 getConnection(url, user, password) 方法来获得连接,其中 url 这个参数不是很好理解:

String url = "jdbc:mysql://localhost:3306/jdbcdemo"; 

其中 jdbc 是协议,mysql 是子协议,localhost 是主机名,3306 是端口号,jdbcdemo 是数据库名。/ 这里的协议是固定地写法,连接不同类型地数据库需要不同地协议。

4.2 Connection

Connection 是连接对象,它可以创建执行 SQL 语句的对象,还可以进行事务的管理。

下面列举了 Connection 类的常用实例方法:

  • Statement createStatement():创建执行 SQL 语句对象,又 SQL 注入风险;
  • PrepareStatement prepareStatement(String sql):预编译 SQL 语句,解决 SQL 注入的漏洞;
  • CallableStatement prepareCall(String sql):执行 SQL 中存储过程;
  • setAutoCommit(boolean autoCommit):设置事务是否自动提交;
  • commit():事务提交;
  • rollback():事务回滚。

4.3 Statement

Statement 是执行 SQL 语句的对象,下面列举了 Statement 类的常用实例方法:

  • boolean execute(String sql):执行 SQL 语句,如果返回的第一个结果为 ResultSet 对象,则返回 true,如果其为更新计数或者不存在任何结果,则返回 false。该方法不常用;
  • ResultSet executeQuery(String sql):执行 SQL 中的 select 语句;
  • int executeUpdate(String sql):执行 SQL 中的 insertupdatedelete 语句,返回影响的行数。

Statement 还可以执行批量操作,关于批量操作,我们将在下面学习。

4.4 ResultSet

ResultSet 是结果集对象,它是 select 语句查询的结果的封装。下面列举了 ResultSet 类的常用实例方法:

  • boolean next():将光标从当前位置向前移一行,判断是否有下一行记录;
  • getString(String columnLable):以 Java 语言中 String 的形式获取此 ResultSet 对象的当前行中指定的值;
  • getInt(String columnLable):以 Java 语言中 int 的形式获取此 ResultSet 对象的当前行中指定的值;
  • getXXX():对于不同类型的数据,可以使用 getXXX() 来获取数据(例如 getString()getInt()),另外还有一个通用的 getObject() 方法,用于获取所有 Object 类型的数据。

4.5 JDBC 资源的释放

JDBC 程序运行完成后,一定要记得释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常是 ResultSetStatement 和 Connection 对象。特别是 Connection 对象,它是非常稀有的资源,用完后必须马上释放,如果此对象不能及时、正确的关闭,极易导致系统的宕机。Connection 对象的使用原则是尽量晚创建,尽量早释放。

5. CRUD

5.1 新增数据

在执行新增数据的代码前,user 表中有如下数据:

mysql> select * from user;
+----+--------------+--------------+----------+
| id | username     | nickname     | password |
+----+--------------+--------------+----------+
|  1 | Colorful     | Colorful3    | 123456   |
|  2 | mybj123      | 小码         | 123456   |
|  3 | Lillian      | 小李         | 123456   |
+----+--------------+--------------+----------+
3 rows in set (0.00 sec)

新增数据的实例代码如下:

package com.mybj.jdbc;import java.sql.*;public class JDBCDemo2 {/*** 插入语句* @return 受影响的行数*/public static int insert() {final String url = "jdbc:mysql://localhost:3306/jdbcdemo";  // 数据库 urlfinal String user = "root"; // 数据库用户名final String password = "123456"; // 数据库密码Connection connection = null;Statement  statement = null;int result = 0;try {// 1. 加载数据库驱动Class.forName("com.mysql.jdbc.Driver");// 2. 建立连接connection = DriverManager.getConnection(url, user, password);// 3. 创建 Statement 对象,用于向数据库发送 SQL 语句String sql = "INSERT INTO `user` VALUES(null, \"testUsername\", \"testNickname\", \"123456\")";statement = connection.createStatement();result = statement.executeUpdate(sql);} catch (Exception e) {e.printStackTrace();} finally {// 4. 释放资源,断开与数据库的连接(调用close()方法)if (statement != null) {try {statement.close();} catch (SQLException e) {e.printStackTrace();}statement = null;}if (connection != null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}// 此处手动设置为 null,有益于垃圾回收机制更早地回收对象connection = null;}}return result;}public static void main(String[] args) {int rows = JDBCDemo2.insert();System.out.println("受影响的行数为:" + rows);}}

运行结果:

受影响的行数为:1

此时,查询数据库中的记录,可以发现多了 1 条:

mysql> select * from user;
+----+--------------+--------------+----------+
| id | username     | nickname     | password |
+----+--------------+--------------+----------+
|  1 | Colorful     | Colorful3    | 123456   |
|  2 | mybj123      | 小码         | 123456   |
|  3 | Lillian      | 小李         | 123456   |
|  4 | testUsername | testNickname | 123456   |
+----+--------------+--------------+----------+
4 rows in set (0.00 sec)

5.2 读取数据

读取数据的示例如下:

package com.mybj.jdbc;import java.sql.*;public class JDBCDemo3 {/*** 根据 id 查询用户* @param id 用户的 id*/public static void selectUserById(int id) {final String url = "jdbc:mysql://localhost:3306/jdbcdemo";  // 数据库 urlfinal String user = "root"; // 数据库用户名final String password = "123456"; // 数据库密码Connection connection = null;Statement statement = null;ResultSet result = null;try {// 1. 加载数据库驱动Class.forName("com.mysql.jdbc.Driver");// 2. 建立连接connection = DriverManager.getConnection(url, user, password);// 3. 创建 Statement 对象,用于向数据库发送 SQL 语句String sql = "SELECT * FROM `user` WHERE id = " + id;statement = connection.createStatement();// 4. 获取 ResultSet 对象,取出数据result = statement.executeQuery(sql);while (result.next()) {String nickname = result.getString("nickname");String username = result.getString("username");String pwd = result.getString("password");System.out.println("id=" + id + "; username=" + username + "; nickname=" + nickname + "; password=" + pwd + '\r');}} catch (Exception e) {e.printStackTrace();} finally {// 5. 释放资源,断开与数据库的连接(调用close()方法)if (result != null) {try {result.close();} catch (SQLException e) {e.printStackTrace();}result = null;}if (statement != null) {try {statement.close();} catch (SQLException e) {e.printStackTrace();}statement = null;}if (connection != null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}// 此处手动设置为 null,有益于垃圾回收机制更早地回收对象connection = null;}}}public static void main(String[] args) throws SQLException {JDBCDemo3.selectUserById(4);}}

运行结果:

id=3; username=Lillian; nickname=小李; password=123456

5.3 更新数据

在执行更新数据的代码前,user 表中有如下数据:

mysql> select * from user;
+----+--------------+--------------+----------+
| id | username     | nickname     | password |
+----+--------------+--------------+----------+
|  1 | Colorful     | Colorful3    | 123456   |
|  2 | mybj123      | 小码         | 123456   |
|  3 | Lillian      | 小李         | 123456   |
|  4 | testUsername | testNickname | 123456   |
+----+--------------+--------------+----------+
4 rows in set (0.00 sec)

更新数据的实例代码如下:

package com.mybj.jdbc;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;public class JDBCDemo4 {/*** 更新* @return 受影响的行数*/public static int updateById(int id) {final String url = "jdbc:mysql://localhost:3306/jdbcdemo";  // 数据库 urlfinal String user = "root"; // 数据库用户名final String password = "123456"; // 数据库密码Connection connection = null;Statement  statement = null;int result = 0;try {// 1. 加载数据库驱动Class.forName("com.mysql.jdbc.Driver");// 2. 建立连接connection = DriverManager.getConnection(url, user, password);// 3. 创建 Statement 对象,用于向数据库发送 SQL 语句String sql = "UPDATE `user` SET `nickname` = '更新后的nickname' WHERE id = " + id;statement = connection.createStatement();result = statement.executeUpdate(sql);} catch (Exception e) {e.printStackTrace();} finally {// 4. 释放资源,断开与数据库的连接(调用close()方法)if (statement != null) {try {statement.close();} catch (SQLException e) {e.printStackTrace();}statement = null;}if (connection != null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}// 此处手动设置为 null,有益于垃圾回收机制更早地回收对象connection = null;}}return result;}public static void main(String[] args) {int rows = JDBCDemo4.updateById(4);System.out.println("受影响的行数为:" + rows);}}

运行结果:

受影响的行数为:1

更新数据代码执行完成后,可以观察到 id 为 4 的记录 nickname 字段发生了改变:

mysql> select * from user;
+----+--------------+----------------------+----------+
| id | username     | nickname             | password |
+----+--------------+----------------------+----------+
|  1 | Colorful     | Colorful3            | 123456   |
|  2 | mybj123      | 小码                 | 123456   |
|  3 | Lillian      | 小李                 | 123456   |
|  4 | testUsername | 更新后的nickname     | 123456   |
+----+--------------+----------------------+----------+
4 rows in set (0.00 sec)

5.4 删除数据

在执行删除数据的代码前,user 表中有如下数据:

mysql> select * from user;
+----+--------------+----------------------+----------+
| id | username     | nickname             | password |
+----+--------------+----------------------+----------+
|  1 | Colorful     | Colorful3            | 123456   |
|  2 | mybj123      | 小码                 | 123456   |
|  3 | Lillian      | 小李                 | 123456   |
|  4 | testUsername | 更新后的nickname     | 123456   |
+----+--------------+----------------------+----------+
4 rows in set (0.00 sec)

删除数据的实例代码如下:

package com.mybj.jdbc;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;public class JDBCDemo5 {/*** 删除* @return 受影响的行数*/public static int deleteById(int id) {final String url = "jdbc:mysql://locahost:3306/jdbcdemo";  // 数据库 urlfinal String user = "root"; // 数据库用户名final String password = "123456"; // 数据库密码Connection connection = null;Statement  statement = null;int result = 0;try {// 1. 加载数据库驱动Class.forName("com.mysql.jdbc.Driver");// 2. 建立连接connection = DriverManager.getConnection(url, user, password);// 3. 创建 Statement 对象,用于向数据库发送 SQL 语句String sql = "DELETE FROM `user` WHERE id = " + id;statement = connection.createStatement();result = statement.executeUpdate(sql);} catch (Exception e) {e.printStackTrace();} finally {// 4. 释放资源,断开与数据库的连接(调用close()方法)if (statement != null) {try {statement.close();} catch (SQLException e) {e.printStackTrace();}statement = null;}if (connection != null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}// 此处手动设置为 null,有益于垃圾回收机制更早地回收对象connection = null;}}return result;}public static void main(String[] args) {int rows = JDBCDemo5.deleteById(4);System.out.println("受影响的行数为:" + rows);}}

运行结果:

受影响的行数为:1

在执行删除数据的代码后,可观察到 id 为 4 的记录被成功删除,数据库只剩下了 3 行记录:

mysql> select * from user;
+----+--------------+----------------------+----------+
| id | username     | nickname             | password |
+----+--------------+----------------------+----------+
|  1 | Colorful     | Colorful3            | 123456   |
|  2 | mybj123      | 小码                 | 123456   |
|  3 | Lillian      | 小李                 | 123456   |
+----+--------------+----------------------+----------+
3 rows in set (0.00 sec)

6. 批量操作

当我们需要向 user 表插入多条数据的时候,可以循环调用我们在上面 JDBCDemo2 实例代码中封装的 insert() 方法,但这样的效率是非常低的。

Statement 对象有如下常用的用于批量操作的方法:

  • void addBatch(String sql):将给定的 SQL 命令添加到此 Statement 对象的当前命令列表中;
  • int[] executeBatch():将一批命令提交给数据库来执行,如果全部命令执行成功,则返回更新计数组成的数组;
  • void clearBatch():清空此 Statement 对象的当前 SQL 命令列表。

7. 小结

通过本小节的学习,我们了解了 JDBC 定义了客户端访问数据库的 API,不同厂商通过实现统一的 JDBC 接口,降低了程序员的学习成本和维护成本。
DriverManager 类用于注册驱动和获得连接;
Connection 是连接对象,它可以创建执行 SQL 语句的对象,还可以进行事务的管理;
Statement 是执行 SQL 语句的对象、ResultSet 是结果集对象,它是 select 语句查询的结果的封装。
为了防止 SQL 注入,推荐使用 PrepareStatement 对象来预编译 SQL 语句,对于内容相同,参数不同的 SQL,推荐使用 JDBC 的 batch 操作,可大大提高执行效率。

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

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

相关文章

AI预测福彩3D采取888=3策略+和值012路或胆码测试6月13日新模型预测第3弹

今天咱们继续验证新模型的8码定位3&#xff0c;目前新模型新算法已连续命中2次。咱们重点是预测8码定位3&#xff0b;和值012胆码。有些朋友看到我最近两篇文章没有给大家提供缩水后的预测详情&#xff0c;在这里解释下&#xff1a;其实我每篇文章中既有8码定位&#xff0c;也有…

数据库学霸笔记

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f4a5;&#x1f4a5;个人主页&#xff1a;奋斗的小羊 &#x1f4a5;&#x1f4a5;所属专栏&#xff1a;C语言 &#x1f680;本系列文章为个人学习…

【MySQL】性能分析

https://www.bilibili.com/video/BV1Kr4y1i7ru/?p78 查看执行频次 查看当前数据库的 INSERT, UPDATE, DELETE, SELECT 访问频次&#xff1a; SHOW GLOBAL STATUS LIKE Com_______; 或者 SHOW SESSION STATUS LIKE Com_______; 慢查询日志 慢查询日志记录了所有执行时间超过指…

【JVM】之常见面试题

文章目录 1.JVM中的内存区域划分2.JVM的类加载机制2.1 加载2.2 验证2.3 准备2.4 解析2.5 初始化2.6 类加载的时机 3 类加载器4.双亲委派模型5.JVM中的垃圾回收策略5.1 找谁是垃圾5.1.1 引用计数法5.1.2 可达性分析法 5.2 释放垃圾5.2.1 标记清除算法5.2.2 复制算法5.2.3 标记整…

CorelDRAW2024永久破解版下载安装全教程!

在设计领域&#xff0c;精准和专业是至关重要的要素。随着技术的飞速发展&#xff0c;设计师们对软件的选择也越发严苛。CorelDRAW 2024中文版及其2024终身永久版、破解版&#xff0c;因其强大的功能和便捷的使用体验&#xff0c;成为了设计师们的首选之一。本文将深入探讨这一…

网络编程入门

文章目录 网络编程入门计算机网络基础计算机网络发展史TCP/IP模型网络应用模式 基于HTTP协议的网络资源访问HTTP&#xff08;超文本传输协议&#xff09;JSON格式requests库 基于传输层协议的套接字编程TCP套接字UDP套接字 网络应用开发发送电子邮件发送短信 网络编程入门 计算…

大模型时代已至,产品经理如何紧跟时代步伐?

前言 在数字化浪潮的推动下&#xff0c;人工智能领域正迎来一场技术革命&#xff0c;而大模型技术的崛起无疑是这场革命中的明星。作为产品经理&#xff0c;我们不仅要洞察市场趋势&#xff0c;更要紧跟技术发展&#xff0c;以创新的思维和敏锐的洞察力&#xff0c;引领产品走…

YOLOv5+单目测距(python)

YOLOv5单目测距&#xff08;python&#xff09; 1. 相关配置2. 测距原理3. 相机标定3.1&#xff1a;标定方法13.2&#xff1a;标定方法2 4. 相机测距4.1 测距添加4.2 细节修改&#xff08;可忽略&#xff09;4.3 主代码 5. 实验效果 相关链接 1. YOLOV7 单目测距&#xff08;p…

每日一题——Python实现PAT甲级1112 Stucked Keyboard(举一反三+思想解读+逐步优化)五千字好文

一个认为一切根源都是“自己不够强”的INTJ 个人主页&#xff1a;用哲学编程-CSDN博客专栏&#xff1a;每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 我的写法 时间复杂度 空间复杂度 总结 我要更强 代码分析 时间复杂度 空间复杂度…

组织创新|AI赋能敏捷实践,助力企业敏捷转型

在工业5.0时代&#xff0c;随着项目变得越来越复杂&#xff0c;对效率的需求也在增长&#xff0c;致力于敏捷转型的组织正在寻求创新的解决方案来应对常见的挑战&#xff1a;工作量不平衡、低效的任务分配和知识孤岛等等。对此&#xff0c;AI等尖端技术的潜力可以帮助实现更高效…

测试多模态模型MiniCPM

目录 模型参考信息&#xff1a; 文件目录&#xff1a; 使用图片&#xff1a; 执行结果&#xff1a; 让模型用中文输出&#xff1a; 评价 模型参考信息&#xff1a; https://huggingface.co/openbmb/MiniCPM-Llama3-V-2_5 文件目录&#xff1a; 使用图片&#xff1a; h…

HCIA14 DHCP 实验

动态主机配置协议 DHCP&#xff08;Dynamic Host Configuration Protocol&#xff09;由 RFC 2131 定义&#xff0c;采用客户端/服务器通信模式&#xff0c;由客户端&#xff08;DHCP Client&#xff09;向服务器&#xff08;DHCP Server&#xff09;提出配置申请&#xff0c;服…

HTML--给网站添加已运行时间的统计

原文网址&#xff1a;HTML--给网站添加已运行时间的统计_IT利刃出鞘的博客-CSDN博客 简介 本文介绍怎么给自己网站添加已经运行了多长时间。 代码 <html lang"cn"><head><meta http-equiv"Content-Type" content"text/html;charse…

KafkaQ - 好用的 Kafka Linux 命令行可视化工具

鉴于并没有在网上找到比较好的linux平台的kafka可视化工具&#xff0c;今天为大家介绍一下自己开发的在 Linux 平台上使用的可视化工具KafkaQ 虽然简陋&#xff0c;主要可以实现下面的这些功能&#xff1a; 1&#xff09;查看当前topic的分片数量和副本数量 2&#xff09;查…

【GlobalMapper】去除数据黑边

tif数据加载出来有这种黑色的边框&#xff0c;使用 Global Mapper切片之后&#xff0c;会有那种黑色的色块加载出来 影像黑边出现的原因&#xff1a; 通常&#xff0c;由于影像格式、像素深度、无效值、背景值等原因&#xff0c;会产生黑边或者白边&#xff0c;给影像的拼接或…

【图书推荐】《Vue.js 3.x+Element Plus前端开发实战》

本书重点 Element Plus是一套采用Vue.js 3.x实现的UI组件库&#xff0c;它为开发者、设计师和产品经理提供了配套设计资源&#xff0c;可以帮助网站快速成型。 本书详解Vue.js 3.x和Element Plus开发方法&#xff0c;配套源码、PPT课件。 内容简介 本书分为两篇&#xff0c…

d3dcompiler_43.dll是什么文件?怎么高效率的解决d3dcompiler_43.dll丢失问题

d3dcompiler_43.dll是什么文件&#xff1f;当你知道d3dcompiler_43.dll这个文件名字的时候&#xff0c;相信你是遇到了d3dcompiler_43.dll丢失的问题了&#xff01;所以才会这样问&#xff0c;其实这就是一个普通的dll文件&#xff0c;对于电脑系统有着至关重要的作用&#xff…

干货分享:宏集物联网HMI通过S7 MPI协议采集西门子400PLC数据

前言 为了实现和西门子PLC的数据交互&#xff0c;宏集物联网HMI集成了S7 PPI、S7 MPI、S7 Optimized、S7 ETH等多个驱动来适配西门子200、300、400、1200、1500、LOGO等系列PLC。 本文主要介绍宏集HMI通过S7 MPI协议采集西门子400PLC数据的操作步骤&#xff0c;其他协议的操作…

【面经总结】Java基础 - IO

序列化 什么是序列化和反序列化&#xff1f; 序列化&#xff1a;将对象转换为二进制数据 反序列化&#xff1a;将二进制数据转换为对象 目的&#xff1a;方便网络传输、持久化保存 Java 是怎么实现序列化的&#xff1f; Java 通过对象输入输出流来实现序列化和反序列化&a…

tp6+swoole+mysql+nginx+redis高并发优化

1.服务器 IDC机房提供的物理机&#xff1a;单机 40核&#xff0c;64G内存&#xff0c;带宽100M&#xff0c; 2.redis 7.2配置 timeout600 #空闲连接超时时间,0表示不断开 maxclients100000 #最大连接数 3.Mysql 5.7配置&#xff0c;按宝塔16-32G优化方案并调整&#xff1a;…