8-JDBC 编程

news2024/11/27 22:20:37

目录

1.数据库编程的必备条件

PS:程序是怎么操作数据库的?

2.什么是JDBC?

2.1.JDBC定义

2.2.JDBC工作原理

3.JDBC使用

3.1.创建项目并添加MySQL驱动包

3.2.使用代码操作数据库

3.2.1.获得数据源

3.2.2.获得连接

3.2.3.获得执行器

3.2.4.查询或操作数据库

3.2.5.关闭数据库连接

执行代码——插入

执行代码——修改、删除

执行代码——查询

PS:使用DriverManager实现查询


1.数据库编程的必备条件

  • 编程语言,如Java,C、C++、Python等。
  • 数据库,如Oracle,MySQL,SQL Server等。
  • 数据库驱动包:不同的数据库,对应不同的编程语言提供了不同的数据库驱动包,如:MySQL提供了Java的驱动包mysql-connector-java,需要基于Java操作MySQL即需要该驱动包。同样的, 要基于Java操作Oracle数据库则需要Oracle的数据库驱动包ojdbc。

PS:程序是怎么操作数据库的?

实际开发中,SQL很少是手动输入的,绝大多数的SQL都是通过代码,自动执行的。重复执行同一条SQL,且不确定执行多少次?就需要让其他编程语言程序来操作数据库服务器。

  • 自己实现数据库客户端很容易,因为各种数据库本身提供了一系列操作的API。官方维护——Oracle。
  • 自己实现数据库服务器就很难了,因为包含存储引擎、使用啥样的数据结构来组织数据,存储数据、SQL执行引擎、基于编译原理能对SQL进行解析和优化。

API:Application Program Interface,好比拿到个啥东西,这个东西能提供哪些功能/服务。

  • Java标准库就提供一些API:这个API里有一些随机数、scanner、集合类等(一组类/方法);
  • C标准库的API:#include<stdio.h>、scanf、printf、fopen、fclose。
  • 操作系统也提供一些API:操作硬盘的文件、访问一下内存的内容、重置一下网卡的状态......包括模拟鼠标事件、模拟硬盘事件(以类/方法提供的);
  • MySQL也会提供一些API(最初是C语言,为了使用广泛,提供了多个其他语言版本的API,其他语言版本的API本质还是调用C的API,跨语言调用)用来操作数据库,完成各种增删改查操作了。

使⽤程序之所以能操作数据库,主要是因为数据库⼚商提供了操作的 API,也就是数据库驱动,驱使数据库⾏动起来。不光是程序,像我们之所以能通过命令⾏操作 MySQL,也是因为 MySQL 的数据库驱动,对于操作界⾯来说,数据库驱动就是:

输⼊的命令就是 MySQL 数据驱动的⼀部分。

数据库驱动包含了数据库操作 API,它们的关系如下:

2.什么是JDBC?

在了解 JDBC 概念之前,先来想⼏个问题:

  • 不同数据库⼚商的数据库驱动⼀样吗?
  • 不同数据库⼚商的 API 调⽤⼀样吗?
  • 使⽤ Java 程序只操作 MySQL 吗?还是有可能操作 Oracle、Sql Server、DB2 等数据库?

以上的答案都是否定的,也就是说不同⼚商提供了不同的数据库驱动,提供了不同的 API 接⼝,那 Java 程序要怎么实现? 难道是针对⼀个数据库写⼀套调⽤的⽅法吗?因为驱动和 API 完全不同,所以不同的数据操作也是不同的,要针对每种数据库写⼀套调⽤代码就太麻烦了,那要怎么办? 解决以上问题的办法就是使⽤ JDBC。

2.1.JDBC定义

JDBC,即 Java Database Connectivity,Java 数据库连接。是⼀种⽤于执⾏ SQL 语句的 Java API, 它是 Java 中的数据库连接规范。这个 API 由 java.sql.*、javax.sql.* 包中的⼀些类和接⼝组成,它为 Java 开发⼈员操作数据库提供了⼀个标准的 API,可以为多种关系数据库提供统⼀访问。

简单来说,使⽤了 JDBC 之后,不管是什么数据库与什么数据库驱动,只需要使⽤⼀套标准代码就可以实现对不同数据库进⾏统⼀操作(添加、修改、删除、查询),也就解决了上⾯说的那些问题了。

C++操作哪个数据库,就使用哪个API。

Java运行在JVM上,C++运行在CPU上。

2.2.JDBC工作原理

JDBC 为多种关系数据库提供了统⼀访问⽅式,作为特定⼚商数据库访问 API 的⼀种⾼级抽象, 它主要包含⼀些通⽤的接⼝类。 JDBC 访问数据库层次结构:

JDBC 优势:

  • Java 语⾔访问数据库操作完全⾯向抽象接⼝编程。
  • 开发数据库应⽤不⽤限定在特定数据库⼚商的 API。
  • 程序的可移植性⼤⼤增强。

3.JDBC使用

3.1.创建项目并添加MySQL驱动包

Oracle官网特别难用,去Maven这个版本的中央仓库下载驱动包:

选择时大版本是5.1即可~和数据库服务器版本对应。

  • 黑客(黑帽子)发现一些软件漏洞(相当于是代码里的bug),对系统进行攻击,进一步入侵操控你的电脑。
  • 白客(白帽子)发现软件漏洞后,通知开发者,赶紧修复。
  • 红客:2001年,中美黑客大战,中国一群黑客入侵美国政府网站,给网站上插红旗,称为红客。

新建文件夹lib。复制刚才下载的jar包,粘贴到lib下。

此时idea就可以解析jar包里包含的内容了。

3.2.使用代码操作数据库

操作数据库 MySQL 提供了两种操作 API:

  • DriverManager
  • DataSource(推荐使⽤)

接下来咱们使⽤ DataSource 来实现操作数据库。 使⽤代码操作数据库分为以下 5 个步骤: 

  1. 获取数据源(准备⼯作,点击 MySQL 连接⼯具,并输⼊⽤户名、密码) 
  2. 获取连接(敲击回⻋试图建⽴客户端和服务器端的连接)
  3. 获取执⾏器(连接到服务器并切换到数据库)
  4. 查询或操作数据库(输⼊命令,并得到结果)
  5. 关闭连接(关闭客户端)

3.2.1.获得数据源

不同的数据库,对于数据源的描述,是存在差异的!有的数据库是通过用户名、密码来认证,有的不是,比如SQLLite。

URL:

  • jdbc:mysql - 这个url是给idbc中的mysql来使用的。
  • 127.0.0.1 - 数据库服务器所在的IP地址,换回IP,表示主机自己(相当于java中的this)只要数据库服务器和jdbc程序是在同一台电脑上,就可以使用这个IP地址。
  • 3306 - 端口号,mysql安装时配置的默认端口号。 
  • java106 - 访问的数据库名。
  • characterEncoding=utf8 - 描述了请求的字符编码方式,一般都设置为utf8。
  • useSSL=false - 关闭数据库加密功能,此处没必要加密,手动关了,如果不关,有些可能会连接失败。
//使用 jdbc 往数据库中,插入一个记录
//需要提前准备好数据库(java106)和数据表(student)

//1.创建数据源,描述了数据库服务器在哪
DataSource dataSource = new MysqlDataSource(); //向上转型
//设置数据库所在的地址和端口以及数据库名,当前是固定写法
((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/java106?characterEncoding=utf8&useSSL=false"); //向下转型
//这样写的好处是后续代码使用DataSource类型的实例,避免MysqlDataSource这个名字扩散到代码的各个地方(高内聚),未来要是换数据库,只改动这一个代码即可

//        //也可以不做任何转型
//        MysqlDataSource mysqlDataSource = new MysqlDataSource();
//        mysqlDataSource.setURL();

//指定数据库登录的用户:root,这是mysql自带的用户,也可配置别的,但基本用不到((MysqlDataSource)dataSource).setUser("root");
//指定数据库登录的密码,密码就是安装数据库的时候,手动设置的密码((MysqlDataSource)dataSource).setPassword("12345678");

3.2.2.获得连接

  • Connection是网络通信中的核心概念,叫“连接”。
  • Link是“链接”。
//2.和数据库建立网络连接,写的 jdbc 代码本质上是实现一个 mysql 客户端,要通过网络和服务器进行通信
Connection connection = dataSource.getConnection();

//通过控制台,来输入用户的信息
Scanner scanner = new Scanner(System.in);
System.out.println("请输入学号:");
int id = scanner.nextInt();
System.out.println("请输入姓名:");
String name = scanner.next();

3.2.3.获得执行器

执⾏器是⽤来执⾏ SQL 命令的,执⾏器有三种:

  1. Statement
  2. PreparedStatement
  3. CallableStatement

实际开发中最常⽤的是 PreparedStatement 对象,PreparedStatement 优点如下:

PreparedStatement 有主要两种重要的⽅法:

  1. executeQuery():⽅法执⾏后返回单个结果集的,通常⽤于 select 语句。
  2. executeUpdate():⽅法返回值是⼀个整数,指示受影响的⾏数,通常⽤于 update、insert、 delete 语句。
//3.构造一个sql语句,来完成插入操作
String sql = "insert into student values(?,?)"; //占位符(1,2)此处不是从0开始计算,而是从1开始计算
//jdbc中还需要搭配一个特定的对象,来描述这里的sql的情况
PreparedStatement statement = connection.prepareStatement(sql); //会对sql语句做一些处理解析,减轻mysql服务器的压力
//填充占位符
statement.setInt(1,id);
statement.setString(2, name);
System.out.println("sql:" + statement);

3.2.4.查询或操作数据库

//4.执行sql语句,控制客户端给服务器发送网络请求,返回结果的含义是这个操作影响到几行
/**
 * 针对增、删、改,使用executeUpdate来执行
 * 针对查,使用executeQuery来执行
 */
int ret = statement.executeUpdate();
System.out.println("ret = " + ret);

3.2.5.关闭数据库连接

//5.断开数据库连接,并且释放必要的资源,资源释放的顺序和创建的顺序是相反的
statement.close();
connection.close();

执行代码——插入

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 JDBCInsertDemo {
    public static void main(String[] args) throws SQLException {
        //使用 jdbc 往数据库中,插入一个记录
        //需要提前准备好数据库(java106)和数据表(student)

        //1.创建数据源,描述了数据库服务器在哪
        DataSource dataSource = new MysqlDataSource(); //向上转型
        //设置数据库所在的地址和端口以及数据库名,当前是固定写法
        ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/java106?characterEncoding=utf8&useSSL=false"); //向下转型
        //这样写的好处是后续代码使用DataSource类型的实例,避免MysqlDataSource这个名字扩散到代码的各个地方(高内聚),未来要是换数据库,只改动这一个代码即可

//        //也可以不做任何转型
//        MysqlDataSource mysqlDataSource = new MysqlDataSource();
//        mysqlDataSource.setURL();

        //指定数据库登录的用户:root,这是mysql自带的用户,也可配置别的,但基本用不到
        ((MysqlDataSource)dataSource).setUser("root");
        //指定数据库登录的密码,密码就是安装数据库的时候,手动设置的密码
        ((MysqlDataSource)dataSource).setPassword("12345678");

        //2.和数据库建立网络连接,写的 jdbc 代码本质上是实现一个 mysql 客户端,要通过网络和服务器进行通信
        Connection connection = dataSource.getConnection();

        //通过控制台,来输入用户的信息
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入学号:");
        int id = scanner.nextInt();
        System.out.println("请输入姓名:");
        String name = scanner.next();

        //3.构造一个sql语句,来完成插入操作
        String sql = "insert into student values(?,?)"; //占位符(1,2)此处不是从0开始计算,而是从1开始计算
        //jdbc中还需要搭配一个特定的对象,来描述这里的sql的情况
        PreparedStatement statement = connection.prepareStatement(sql); //会对sql语句做一些处理解析,减轻mysql服务器的压力
        statement.setInt(1,id);
        statement.setString(2, name);
        System.out.println("sql:" + statement);

        //4.执行sql语句,控制客户端给服务器发送网络请求,返回结果的含义是这个操作影响到几行
        /**
         * 针对增、删、改,使用executeUpdate来执行
         * 针对查,使用executeQuery来执行
         */
        int ret = statement.executeUpdate();
        System.out.println("ret = " + ret);

        //5.断开数据库连接,并且释放必要的资源,资源释放的顺序和创建的顺序是相反的
        statement.close();
        connection.close();
    }
}

执行代码——修改、删除

和插入的代码非常像,只需改动sql语句即可~

执行代码——查询

查询数据库使⽤ PreparedStatement.executeQuery ⽅法,返回⼀个 ResultSet 对象。

ResultSet 对象它被称为结果集,它代表符合 SQL 语句条件的所有⾏,并且它通过⼀套 getXXX ⽅法提供了对这些⾏中数据的访问。

ResultSet ⾥的数据⼀⾏⼀⾏排列,每⾏有多个字段,并且有⼀个记录指针,指针所指的数据⾏叫做当前数据⾏,我们只能来操作当前的数据⾏。我们如果想要取得某⼀条记录,就要使⽤ ResultSet 的 next() ⽅法 ,如果我们想要得到 ResultSet ⾥的所有记录,就应该使⽤ while 循环。

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 JDBCSelectDemo {
    public static void main(String[] args) throws SQLException {
        DataSource dataSource = new MysqlDataSource();
        ((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/java106?characterEncoding=utf8&useSSL=false");
        ((MysqlDataSource)dataSource).setUser("root");
        ((MysqlDataSource)dataSource).setPassword("12345678");

        Connection connection = dataSource.getConnection();

        String sql = "select * from student where id>?";
        PreparedStatement statement = connection.prepareStatement(sql);
        statement.setInt(1,2);

        ResultSet resultSet = statement.executeQuery();
        while(resultSet.next()) {
            //next初始情况下,光标指向第一行的前面,移动一下光标,光标指向下一行,然后移动到结尾,就返回 false
            //使用getXX方法获取到每一列
            //获取int,就使用getInt,获取String,就使用getString
            //这里的参数,就是数据库表的列名
            int id = resultSet.getInt("id");
            String name = resultSet.getString("name");
            System.out.println(id + ":" + name);
        }

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

PS:使用DriverManager实现查询

jdbc支持2种风格的代码,一个是DriverManager,一个是DataSource。

  1. DriverManager使用时,需要借助反射,反射不属于常规的编程手段,是特殊情况下的特殊手段。
  2. DataSource相比于DriverManager,内置了数据库连接池,可以重复利用连接。 推荐使用DataSource。

使⽤ DriverManager 只是获取 Connection 之前的两步代码不⼀样:

import java.sql.*;

public class App2 {
    public static void main(String[] args) throws SQLException, ClassNotFoundException {
        // 1.加载JDBC驱动程序:反射,这样调⽤初始化com.mysql.jdbc.Driver类,即将该类加载到JVM⽅法区,并执⾏该类的静态⽅法块、静态属性。
        Class.forName("com.mysql.jdbc.Driver");
        // 2.创建数据库连接
        Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/java33?user=root&password=12345678&characterEncoding=UTF-8&useSSL=true");
        // 3.获得执⾏器
        PreparedStatement statement = connection.prepareStatement("select * from student where username=?");
        // 3.1 占位符赋值
        statement.setString(1, "王五");
        // 4.获得结果集
        ResultSet resultSet = statement.executeQuery();
        // 4.1 获得结果并打印
        while (resultSet.next()) {
            String sn = resultSet.getString("sn");
            String username = resultSet.getString("username");
            String mail = resultSet.getString("mail");
            System.out.println(String.format("SN:%s,UserName:%s,Mail:%s", sn, username, mail));
        }
        // 5. 关闭资源
        resultSet.close();
        connection.close();
    }
}

实际开发中,用框架Mybatis,JPA这些框架来代替JDBC。

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

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

相关文章

软考A计划-2022年11月软件设计师下午真题及答案解析

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

【云原生|Kubernetes】06-Pod的生命周期和重启策略

【云原生|Kubernetes】06-Pod的生命周期和重启策略 文章目录 【云原生|Kubernetes】06-Pod的生命周期和重启策略Pod生命周期生命周期Pod的状态Pod子状态 Pod重启策略调试PodPod 停滞在 Pending 状态Pod 停滞在 Waiting 状态Pod 处于 Crashing 或别的不健康状态Pod 处于 Running…

【LeetCode热题100】打卡第4天:寻找两个正序数组的中位数

文章目录 寻找两个正序数组的中位数⛅前言&#x1f512;题目&#x1f511;题解 寻找两个正序数组的中位数 ⛅前言 大家好&#xff0c;我是知识汲取者&#xff0c;欢迎来到我的LeetCode热题100刷题专栏&#xff01; 精选 100 道力扣&#xff08;LeetCode&#xff09;上最热门的…

89.qt qml-WorkerScript多线程使用(无需C++代码)

由于我们自定义Table中需要实现排序,如下图所示: 考虑到如果数据量太大的情况,为了避免主线程阻塞,所以我们添加多线程排序功能,为了方便大家更好学习qml组件,所以学习WorkerScript实现多线程,无需C++ 1.描述 使用 WorkerScript 在新线程中运行操作。这对于在后台运行操…

微信小程序为什么不用HTML5、CSS,自己搞了个WXML、WXSS,很多框架用不了,好处一点不知道?

你在小程序中需要使用HTML5、 CSS来创建页面&#xff0c;那么你一定会碰到一些问题&#xff0c;比如&#xff1a; 1.小程序中的布局没有 JS支持&#xff0c;没有 JS渲染逻辑。 2.没有内置 css&#xff0c;都是靠 JS自己实现的。 3.很多框架不能使用&#xff0c;比如&#xf…

5年华为外包,外包究竟怎么样....

最近身边很多人进了外包或者被问到进到外包公司怎么样&#xff0c;感觉大家对外包公司不是很了解&#xff0c;也有一些误解&#xff0c;我们看看过来人怎么说。 5年外包时光 我曾是华为外包软件测试员工&#xff0c;就职于东莞松山湖&#xff0c;2017年9月12号入职&#xff0c…

ARM--计算机基础知识

目录 一.Linux层次结构 谈谈对嵌入式的理解 三层&#xff1a; 应用层 内核层 硬件层 二、计算机的进制 三、计算机的组成 1.输入设备 2.输出设备 3.存储器 4.运算器 5.控制器 总线 四、ARM存储模型 1. Cache:高速缓冲存储器 2. 主存储器&#xff1a;相当于内存 …

Day1:手写第一个Win32程序

学习重点&#xff1a; 1. 理解这个Win32窗口程序的实现逻辑 2. 学习Windows消息循环机制 3. 了解Windows的数据类型 4. 明白Winmain函数的作用 首先这个Winodws窗口程序在之后的学习并不需要进行手写&#xff0c;这里的重点是学习代码的逻辑&#xff0c;虽然有一些参数的含义尚…

vue3 集成kindeditor研究

kindeditor虽然老&#xff0c;但是稳定&#xff0c;最大的好外是word贴进去不变形&#xff0c;后端部分有安全隐患&#xff0c;我给去掉了&#xff0c;只保留了前端&#xff0c;集成jquery添加了跨域ajax上传功能。 用iframe引用实属无奈&#xff0c;因为尝试了好多次用ts封装都…

如何在华为OD机试中获得满分?Java实现【快速开租建站】一文详解!

✅创作者:陈书予 🎉个人主页:陈书予的个人主页 🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区 🌟专栏地址: Java华为OD机试真题(2022&2023) 文章目录 1. 题目描述2. 输入描述3. 输出描述4. Java算法源码5. 测试6.解题思路1. 题目描述 当前IT部门支撑了子公司…

【2023年电工杯竞赛】B题 人工智能对大学生学习影响的评价 数学建模方案和python代码

1 题目 B题 人工智能对大学生学习影响的评价 人工智能简称AI&#xff0c;最初由麦卡锡、明斯基等科学家于1956年在美国达特茅斯学院开会研讨时提出。 2016年&#xff0c;人工智能AlphaGo 4:1战胜韩国围棋高手李世石&#xff0c;期后波士顿动力公司的人形机器人Atlas也展示了…

【PICO G2 4K】 + 【Unity2020.3.40】 :Android 发布设置

一、【设备】设置 设备开始USB调试模式&#xff0c;然后用usb线连接到电脑&#xff0c;识别后下拉框会显示该设备 二、【脚本调试】的Debug设置 如果要在PICO上读取脚本的Debug信息&#xff0c;则需要开启下图中选项&#xff0c;并配置adb工具读取log日志。 参考之前的blog…

学了两个多月软件测试,顺利过了试用期,拿到12K的我很满足了

先介绍一下&#xff0c;我是机械专业的&#xff0c;在一个大厂做售后工程师&#xff08;就是修东西的&#xff09;&#xff0c;做了几年没啥成绩&#xff0c;年龄越大&#xff0c;心里压力也越大&#xff0c;而且这种大型设备维修很容易出事故&#xff0c;就想着搞一门好点的技…

软件测试面试题【内附超详细面试宝典】

一般软件测试的面试分为三轮&#xff1a;笔试&#xff0c;HR面试&#xff0c;技术面试。 前两轮&#xff0c;根据不同企业&#xff0c;或有或无&#xff0c;但最后一个技术面试是企业了解你“行不行”的关键环节&#xff0c;每个企业都会有的。 在平时的学习、工作中一定要善…

《Zookeeper》从零开始学Zookeeper源码(一)之源码环境搭建

目录 源码环境搭建1. 下载源码2. 编译3. Eclipse启动服务端4. 启动客户端 源码环境搭建 1. 下载源码 下载地址&#xff1a; github 2. 编译 进入下载好的源码的根目录&#xff0c;因为下载依赖的时候需要apache的maven元数据&#xff0c;目前最高的版本为3.8.0-SNAPSHOT&am…

【分享】科大讯飞星火认知大模型(初体验)

前言&#xff1a; 哈喽&#xff0c;大家好&#xff0c;我是木易巷~ 随着人工智能技术的迅猛发展&#xff0c;自然语言处理&#xff08;NLP&#xff09;成为了热门话题。在众多NLP模型中&#xff0c;科大讯飞星火认知大模型成为了一个备受瞩目的新秀&#xff0c;今天我们来了解…

C++中string::npos 的使用

string::npos 的作用 string::npos 的意思:The constant is the largest representable value of type size_type. It is assuredly larger than max_size(); hence it serves as either a very large value or as a special code. 大致意思 是一个常量, 是size_type类型,是一…

策略模式-类型统计

文章目录 前言一、策略模式是什么&#xff1f;二、策略模式应用场景三、策略模式优点四、策略模式缺点五、场景案例&#xff1a;类型统计1.项目结构2.UML图解3.代码实现3.1 指标枚举3.2 请求体3.3 响应体3.4.分析统计指标策略3.5.接口3.6.扩展接口3.7.接口实现3.8.控制层 六、P…

2023年本科应届生,金融转行做数据分析有前景吗?

当然有前景的&#xff0c;尤其是数据分析本身的发展前景是无限的&#xff1b;而作为个人而言&#xff0c;只要你专业技能掌握得好&#xff0c;对于业务的理解分析能力过关&#xff0c;也是非常有发展前景的&#xff0c;尤其是在数据分析人才紧缺的阶段&#xff0c;众多行业领域…

直播预告:聚焦盗号 企业邮件安全的威胁分析与应对

根据Coremail邮件安全人工实验室数据监测&#xff0c;2023年Q1全国企业级用户遭受超过17.45亿次暴力破解&#xff0c;虽然无差别的暴力破解攻击从去年Q4开始有相当幅度的下降趋势&#xff0c;但在今年2-3月&#xff0c;全域暴力破解攻击次数又开始回升。 根据Coremail邮件安全专…