【MySQL】Linux下如何用语言连接数据库?

news2024/12/23 11:35:40

用语言连接数据库

  • 前言
  • 正式开始
    • 创建一个等会专门演示语言连接的库和用户
    • 连接mysql要用到的动静态库以及头文件
      • 手动下载mysql官方提供的库(可以跳过不看)
      • 下载MySQL时自动安装的库
    • 用C连接数据库
      • 官方文档
      • 对于编译链接的解释
      • 对库的操作
        • 函数接口介绍
          • mysql_init()
          • mysql_close()
          • mysql_real_connect()
      • select 查找
      • 正常的使用方式
        • 仅查找
        • 仅插入
    • mysql图形化界面
      • Mysql连接池原理

在这里插入图片描述

前言

在我讲第一篇MySQL的博客中我就说过,MySQL是一个网络服务,学过网络的同学应该是懂的,我们想要获取到MySQL的服务,必须要连接mysql的服务器,我们在下载MySQL的时候有两个程序很重要,一个是mysqld,就是MySQL的服务器,一个是mysql,就是MySQL的客户端。

当我们启动MySQL服务器后,用netstat可以查看到我们主机中的mysql服务器:
在这里插入图片描述
我这里就不把我的mysqld的端口暴露出来了,这里也不建议你将你自己mysql服务器的端口暴露到网络中。

刚下载好的默认端口是3306,我这里修改了。如果你也想修改你的端口,只需要修改一下/etc/my.cnf配置文件就行:
在这里插入图片描述

这里改好之后记得用systemctl restart mysqld来重启你的服务器:
在这里插入图片描述

前面博客中一直是用mysql客户端连接数据库,并以命令行的方式来获取MySQL的服务,我前面也演示过远端连接其他主机的MySQL服务器。

那么这一篇就用语言来连接mysql服务器,本篇是用C语言演示的,不过学会这一个其他语言也就会了。

正式开始

创建一个等会专门演示语言连接的库和用户

我这里先来创建一个专门用来演示进行连接的用户:
在这里插入图片描述

关于用户管理的内容我前一篇已经讲过了,本篇不再细说,不懂的同学可以看看我前一篇。

再专门建一个库,给这个用户赋权:
在这里插入图片描述

用这个用户登录并查看权限:
在这里插入图片描述

正常。

连接mysql要用到的动静态库以及头文件

手动下载mysql官方提供的库(可以跳过不看)

我这里先介绍一下mysql官方所提供的库,其实我们在下载MySQL的时候已经将改装的库都装好了,不过这里只是介绍一下这些库都在什么地方。

MySQL的官方:MySQL

上面这个是中文官方页面,也有英文的:MySQL

进去之后点击下载(或者英文页面中的download):
在这里插入图片描述

进去之后往下翻,有个MySQL Community(GPL) Downloads:
在这里插入图片描述
点进去之后选择Download Archives:
在这里插入图片描述

本篇用C语言连接,所以用的是C API,点开之后是这样:
在这里插入图片描述

点中间的MySQL Connector/C,进去之后可以选择你对应mysql的版本:
在这里插入图片描述

不过可以看到下面提供的mysql版本是6.几的,你可以先查看一下你的mysql版本:
在这里插入图片描述

我的是5.几的,其实高版本是兼容我的版本的,所以这里很多的历史版本都没有,直接用新的就行:

在这里插入图片描述

再选择你os的版本,我等会是用Linux来演示,所以os版本选的是Linux的:
在这里插入图片描述

我这里下载好后并发送到我Linux上就是这样的:
在这里插入图片描述

用tar -xvzf进行解压:
在这里插入图片描述

然后会形成一个同名目录:
在这里插入图片描述

如果你嫌目录名太长了可以用mv命令来重命名:
在这里插入图片描述

里面文件有:
在这里插入图片描述

就两个比较重要,一个是include,表示包含头文件的目录:
在这里插入图片描述
其中mysql.h最重要,等会引的时候只需要引这个文件就行了。

一个lib,表示包含库文件的目录:
在这里插入图片描述
.a的为静态库,.so的为动态库。

这个手动下载库就到这,下面来说下载好MySQL就自带的库。

下载MySQL时自动安装的库

其实我们用yum install -y mysql-devel就可以把所有该下载的库都下好:
在这里插入图片描述

然后就会在/user/include下产生一个mysql目录:
在这里插入图片描述
这个目录下中保存的就是要用的头文件:
在这里插入图片描述

还有/lib64下也会生成一个mysql目录:
在这里插入图片描述
这个目录下保存的是需要用到的库文件:
在这里插入图片描述

这些东西搞好了之后就可以测试一下能不能连接上数据库了。

用C连接数据库

官方文档

mysql官方为我们提供的这些库,里面有很多的接口,不同的语言不一样,这些接口需要我们自己摸索着用,所以用语言连接数据库并发送相关的命令是需要我们再学习的,官网中也给我们提供了相关的文档介绍,这里我来简单介绍点接口。

进入官网之后先点击documentation:
在这里插入图片描述

然后往下稍微翻一点,有一个connector & APIS:
在这里插入图片描述

选择你想查看的语言对应的接口介绍,这里我用的是C,那我就选的是C API,后面带加号的表示还要选择不同版本:
在这里插入图片描述

我的mysql是5.7的,所以我选的是这个:
在这里插入图片描述

进去之后选择:

在这里插入图片描述

就可以查看所有函数的介绍了:
在这里插入图片描述

mysql官方提供了很多函数,我这里只截取了一部分。

虽然有很多函数,但是常用的还是那么些。

里面有个mysql_get_client_info函数,先用这个函数测试一下:
在这里插入图片描述

mysql官方里面是有这些函数的介绍的:
在这里插入图片描述

这个函数返回客户端对应的库版本。

对于编译链接的解释

上面的代码如果我直接进行简单的g++会报错的:
在这里插入图片描述

这里说mysql_get_client_info没有定义,并不是没有定义。

mysql为我们提供的库是第三方库,g++在进行编译的时候只会去找C++的库,其中会找一个路径,就是刚刚提到的/lib64下面,虽然刚刚看到了库的目录mysql放到了这个/lib64目录下,但是编译的时候是不会自动去/lib64/mysql中去找的。所以我们在编译的时候要手动加上连接的库以及库对应的目录:
在这里插入图片描述

关于这一点我在前面文件IO的博客讲过,不懂的同学可以看看:看动静态库的制作和使用。

如果你编译出来后运行失败,可能是因为你动态库没有连接上,可以ldd一下:

在这里插入图片描述
如果你是动态库没连上,那箭头右边就是not found,我这里给两种方法:

  1. 在/etc/ld.so.conf.d/目录下将动态库的路径添加到系统配置文件中:
    在这里插入图片描述
    在这个路径下面加上一个.conf文件,文件中放的是库文件所在的路径就行:
    在这里插入图片描述

  2. 将库路径放在环境变量中,这里就不说了,在我那篇博客中详细说了

还有一个-I(这里不是l(L),而是I(i)),-I是指明头文件位置的,不过这里不用加,因为我们在引用头文件的时候是#include <mysql/mysql.h>的,刚刚也看到了/usr/include下是有mysql头文件目录的,搜索的时候会到include目录下面搜索,在搜索头文件的时候是指明了头文件所在目录的,也就是mysql目录,所以会直接进入该目录中找mysql目录下的mysql.h。如果这段话你听不懂,可以去看刚刚给的博客。

如果我是直接#include<mysql.h>,那么就要指明mysql.h所在的路径:
在这里插入图片描述
这里vscode自动报错了。

编译的时候加上-I选项:
在这里插入图片描述

编译:
在这里插入图片描述

成功。

所以小总结一下:

#include指明引用哪个头文件
-I(i)指明头文件位置
-l指明链接哪个库文件
-L指明库文件的位置

对库的操作

C/C++对库的操作,要在官网中查看有哪些函数接口。

库中会有很多的数据结构:
在这里插入图片描述这里有很多数据结构,不过最常用的就前几个。

函数接口介绍

在进行mysql的操作前一定要先连接上mysql服务器,而连接前还要创建一下mysql提供的一些基础数据结构。

mysql_init()

在这里插入图片描述
这个函数会帮我们创建一个MYSQL类型的对象,MYSQL就是一个结构体:

typedef struct st_mysql
{
  NET		net;			/* Communication parameters */
  unsigned char	*connector_fd;		/* ConnectorFd for SSL */
  char		*host,*user,*passwd,*unix_socket,*server_version,*host_info;
  char          *info, *db;
  struct charset_info_st *charset;
  MYSQL_FIELD	*fields;
  MEM_ROOT	field_alloc;
  my_ulonglong affected_rows;
  my_ulonglong insert_id;		/* id if insert on table with NEXTNR */
  my_ulonglong extra_info;		/* Not used */
  unsigned long thread_id;		/* Id for connection in server */
  unsigned long packet_length;
  unsigned int	port;
  unsigned long client_flag,server_capabilities;
  unsigned int	protocol_version;
  unsigned int	field_count;
  unsigned int 	server_status;
  unsigned int  server_language;
  unsigned int	warning_count;
  struct st_mysql_options options;
  enum mysql_status status;
  my_bool	free_me;		/* If free in mysql_close */
  my_bool	reconnect;		/* set to 1 if automatic reconnect */

  /* session-wide random string */
  char	        scramble[SCRAMBLE_LENGTH+1];
  my_bool unused1;
  void *unused2, *unused3, *unused4, *unused5;

  LIST  *stmts;                     /* list of all statements */
  const struct st_mysql_methods *methods;
  void *thd;
  /*
    Points to boolean flag in MYSQL_RES  or MYSQL_STMT. We set this flag 
    from mysql_stmt_close if close had to cancel result set of this object.
  */
  my_bool *unbuffered_fetch_owner;
  /* needed for embedded server - no net buffer to store the 'info' */
  char *info_buffer;
  void *extension;
} MYSQL;

这个MYSQL结构体有很多保存连接的字段,用来标识MySQL客户端相关的资源,就像C中的FILE、系统中的fd一样,都是用来唯一标识某些资源的,都可以被称为句柄。

mysql_init()调用成功会返回一个MYSQL对象,失败了会返回空。

传参的时候给一个nullptr就会直接创建新对象。

mysql_close()

这里的MYSQL就像C中的FILE一样,创建好了之后在最后还要关闭,关闭的函数就是mysql_close:
在这里插入图片描述

传入的就是mysql_init()创建出来的MYSQL对象指针,用来关闭连接,释放资源等。

来写写代码:
在这里插入图片描述

mysql_real_connect()

在这里插入图片描述

第一个参数就是刚刚创建出来的my。

host就是主机是哪台,本篇就测试本地中的mysql服务器,所以等会传localhost或者127.0.0.1就行。

user为连接服务器所用的用户,就是root或普通用户啥的。

paswd就是用户对应的密码。

db就是你在以user身份登录的时候要选择哪个数据库。等会就是用最开始创建的那个conn库来演示,不过这个库是空的,等会演示的时候再创建表。

port即mysql服务器的端口号(这里根据自己设定的端口来定,你可以用netstat -nltp来查看你的端口是啥)。

mysql在本地服务时采用域间套接的方式,类似于管道那样直接和mysql服务端通信,不走网络的那一套。这里不管是域间套接还是网络,后面两个参数设置为nullptr和0就行。

mysql_real_connect调用成功就返回传入的my,失败就返回空,有点像strcpy,成功了就返回原串。

写写代码:
在这里插入图片描述

这样就可以连接数据库了。

这里我加上sleep来测试一下:
在这里插入图片描述

运行,用processlist查看连接的用户信息:
在这里插入图片描述

10s后:
在这里插入图片描述

可以看到很成功。

有一个mysql_query:
在这里插入图片描述
这个函数会将我们传入的stmt_str作为一条sql语句去执行。

执行成功返回0,失败返回非零值。

来写一个创建表的语句:
在这里插入图片描述

这里是可以执行的:
在这里插入图片描述

desc:
在这里插入图片描述

mysql_query的时候传入的sql不需要加分号或者\G。

其实我们完全可以根据mysql_query来写一个我们自己的mysql客户端,不过这样做意义不大,但还是演示一下吧。

我这里先用mysql客户端插入几条记录:
在这里插入图片描述

然后再来改改代码:
在这里插入图片描述

更新:
在这里插入图片描述

删除:
在这里插入图片描述

插入:
在这里插入图片描述

前面我都是可以的在插入英文,如果我现在插入一个中文:
在这里插入图片描述
可以看到乱码了。

这里写的这个相当于是我自己的客户端,就和mysql客户端是一个性质的东西,我这里设置了mysql客户端的默认编码就是UTF8,和服务端一样:
在这里插入图片描述

但是我手写的这个简易客户端并没有设置,可以用mysql_get_character_set_info这个接口来查看当我们手写的这个客户端当前的编码:
在这里插入图片描述

运行:
在这里插入图片描述

或者直接用mysql_character_set_name:
在这里插入图片描述
在这里插入图片描述

可以看到是拉丁的编码,肯定和我们服务端UTF8的编码不匹配,所以我们要手动设置一下我们这个客户端的编码,用mysql_set_charcter_set函数:
在这里插入图片描述
运行:
在这里插入图片描述

这样将编码修改后,就可以插入中文了:
在这里插入图片描述
成功。

再来演示一下退出:

执行ctrl + d试试:
在这里插入图片描述

正常退出。

输入quit:
在这里插入图片描述
也是正常退出。

select 查找

前面的这三个增删改都能成功,但是查找还不行:
在这里插入图片描述
因为查找的结果需要我们自己提取。这里mysql_query只是执行以下sql而已,结果并没有返回,不过单次执行的结果会放到刚刚最开始创建出来的my对象中,我们需要将其中的返回结果手动提取出来。

用mysql_store_result函数:
在这里插入图片描述

可以看到这个函数参数就是刚刚的my,返回一个MYSQL_RES结构体的指针,来看看这个结构体中有什么:
在这里插入图片描述
很多字段。

从这里开始的代码,就和前面的创建的my对象没有什么关系了,后面只用这个MYSQL_RES的对象。

函数返回nullptr的时候有两种情况,一种是执行了非select语句的(比如update、delete、insert),这种不需要什么返回结果,只需要mysql_query的返回值就够了。一种是直接出错了,所以如果是返回空的时候要用其他函数来检查一下,具体我就不说了,看官方的文档介绍:
在这里插入图片描述

我们用select查找出来的结果中可能会有多条记录,而且多条记录中还会有很多不同列的字段,比如说用mysql客户端查找出来的表格:
在这里插入图片描述

把其中的格子去掉:
在这里插入图片描述

当我用我自己写的这个简易客户端执行select语句后,上面的这些数据就会全部被保存在MYSQL_RES这个结构体中。

不管库中的数据是以什么类型存放的,读取出来的时候都是当做字符串来看的。也就是说上面去掉框框的这些数据都是拿出来之后都是字符串,以字符串的形式保存在MYSQL_RES中的。

来搞一个全是元素为char*的二位数组:
在这里插入图片描述

对应的,将这个数组中的char*指针指向上面的所有数据:
在这里插入图片描述
中间的没有画,我怕一下子给画乱了,反正你懂我意思就行,就是一个char*指向一个字符串,一一对应。

所以其实可以把MYSQL_RES这个结构体当做二位数组来看。

我们可以通过mysql_num_rows来获取表的行数,用mysql_num_fields来获取表的列数:
在这里插入图片描述
但是如果不是select函数就会返回空,那么就不会有这些结果:
在这里插入图片描述
在这里插入图片描述

但是我们不仅要知道有多少列,重要的是获取出来其中的结果,所以要想办法遍历结果集,就像遍历上面的那个元素为char*的二维数组一样,把每一个元素所指向的字符串搞出来,mysql为了支持我们进行遍历,内部提供了MYSQL_ROW类型,可以获取到二维数组中的每一行,

其实这个类型就是char**:
在这里插入图片描述

其实也很好理解,假如说上面的二维数组为char* arr[x][y],第一个元素类型为char*,如果想要找到第一个元素的地址,那么就是char** ,这样就等于是一整行的地址就找到了。但是有很多行,底层就会类似这样的方式来找对应行:
在这里插入图片描述

我们通过mysql_fetch_row函数来获取每一行:
在这里插入图片描述

这个传入res,返回一个char**,而且调用这个函数会自动帮我们提取到下一行,就像范围for一样,自动迭代。

拿到一个MYSQL_ROW对象之后就可直接向数组一样用就行。

代码如下:
在这里插入图片描述

运行:
在这里插入图片描述

这样就能查到所有的数据了。

不过没有拿到每一列的列类型,要用另一种数据结构MYSQL_FIELD,也是个结构体:
在这里插入图片描述
里面字段很多,倒数第二个字段type,类型为enum_filed_types,这个类型要说一下:
在这里插入图片描述
其中就是所有的数据类型,当我们拿到了全是字符串的数据后,想要转回原来的数据类型,就可以根据type字段来提取。

调用mysql_fetch_fields:
在这里插入图片描述

返回值为MYSQL_FIELD类型的指针。用的时候也可以像刚刚的MYSQL_ROW的对象一样:
在这里插入图片描述

运行:
在这里插入图片描述

就和mysql客户端打印出来的结果是一样的。
MYSQL_FIELD中还有很多字段,比如说db表示当前选中了哪个数据库,table表示当前是哪一张表:
在这里插入图片描述
所以其实我们就可以控制一下打印格式,加上那些框框啥的,就和mysql客户端一样了,不过这样做没啥意义。

记得用完这个MYSQL_RES的结构体的对象后要释放掉对应的空间,这个结构体字段很多,占用空间还是不小的,用mysql_free_result就可以:
在这里插入图片描述

其实前面的res可以直接写到if的判断里面:
在这里插入图片描述

这样就可以根据res来分成一个模块,正好。

正常的使用方式

仅查找

我们平时用语言连接上数据库之后不是这样写一个死循环,然后再输入得到结果,要是这样的话不如直接用mysql客户端,一般都是针对于某一个功能只执行一条语句,比如说我只想要查询,那就只执行查询的sql,不加循环:
在这里插入图片描述

直接运行就是结果:
在这里插入图片描述

去除掉杂七杂八的打印:
在这里插入图片描述
这样就能打印成功。

仅插入

光是一个插入的,那就更简单了,都不需要MYSQL_RES了。

代码:
在这里插入图片描述

运行:
在这里插入图片描述

mysql图形化界面

mysql的图形化界面有不少,像Navicat、SQLyog都是比较好用的,不过二者要收费,你可以用破解版的,不过我这里就不说怎么搞了,感兴趣的老铁自行百度。

介绍一下MYSQL Workbench,这是个MYSQL官方提供的图形化界面,不过用起来没有上面的Navicat和SQLyog爽。

下载MYSQL Workbench,直接进MYSQL官网就行,跟着我步骤来:
在这里插入图片描述

往下翻:
在这里插入图片描述

进去之后:
在这里插入图片描述

进去后:
在这里插入图片描述

win下就一个版本,直接下就行。

不过下载时,你要有一个Oracle的账户,登陆之后选择一下你的身份信息啥的就能直接下载安装包了。

安装的时候一路next就行(你可以换一下安装路径)。

安装好之后长这样:
在这里插入图片描述

图形化界面本质上也是一个客户端,但我这里没有加上我Linux下的远端MYSQL服务端,我先专门新建一个用户:
在这里插入图片描述

然后再将conn库的权限给这个用户:
在这里插入图片描述
下面给我的workbench添加一个远端登录的用户:
在这里插入图片描述

然后就会有对应的连接:
在这里插入图片描述

登录:
在这里插入图片描述

左侧能选择表:
在这里插入图片描述

里面可以输入sql:
在这里插入图片描述

选中输入的sql然后按那个闪电就可以运行,还会有语法提示。

一些按键,比如说删除:
在这里插入图片描述
点一下就删了,很方便:
在这里插入图片描述

也可以手动插入:
在这里插入图片描述

点击红色框住的Apply就可以查看对应的sql:
在这里插入图片描述

再按一下Apply就执行了:
在这里插入图片描述

对应的远端也能看到:
在这里插入图片描述

就介绍到这,想要深入了解的同学可以自行学学。

Mysql连接池原理

像刚刚那样,连接一个客户端后发送一个sql就直接关闭连接,其实这样做挺浪费资源的,不如搞一个线程池,池中每个线程都连接数据库服务器,并维护一个任务队列,当有任务时就让线程拿任务,没有任务就让线程等待。

具体做法就不细说了,不懂的同学可以看看我线程池的那篇博客。

前面完整代码:

#include<iostream>
#include<mysql/mysql.h>
#include<unistd.h>

#include<string>

const std::string host = "localhost";
const std::string user = "connector";
const std::string passwd = "123456";
const std::string db = "conn";
const unsigned int port = xxxx; // 端口就不给了

int main()
{
    MYSQL* my = mysql_init(nullptr);

    if(mysql_real_connect(my, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0) == nullptr)
    {
        std::cerr << "mysql_real_connect err" << std::endl;
        exit(1);
    }

    // std::string tmp = "select * from user";
    
    std::string tmp = "insert into user (name,age,telphone) values ('fangzhang', 20, 5235134113)";
    int ret = mysql_query(my, tmp.c_str());

    if(ret == 0)
    {
        std::cout << "success" << std::endl;
    }
    else
    {
        std::cout << "err" << std::endl; 
    }
    
    mysql_close(my);
        
    // if(MYSQL_RES* res = mysql_store_result(my))
    // {
    //     int rows = mysql_num_rows(res);
    //     int fields = mysql_num_fields(res);

    //     MYSQL_FIELD* fieldArr = mysql_fetch_fields(res);
    //     for(int j = 0; j < fields; ++j)
    //     {
    //         std::cout << fieldArr[j].name << '\t';
    //     }

    //     std::cout << std::endl;

    //     for(int i = 0; i < rows; ++i)
    //     {
    //         MYSQL_ROW rowArr = mysql_fetch_row(res);
    //         for(int j = 0; j < fields; ++j)
    //         {
    //             std::cout << rowArr[j] << '\t';
    //         }
    //         std::cout << std::endl;
    //     }

    //     mysql_free_result(res);
    // }

   

        // 建个表
    // const std::string tmp = "\
    // create table user(\
    //     id bigint primary key auto_increment,\
    //     name varchar(32) not null,\
    //     age int not null,\
    //     telphone varchar(32) unique\
    // );";


        // 编码
    // MY_CHARSET_INFO charset_info;
    // mysql_get_character_set_info(my, &charset_info);
    // printf("Character set name: %s\n", charset_info.name);
    // printf("Character set name: %s\n", mysql_character_set_name(my));
    // 
    // mysql_set_character_set(my, "utf8");
    // 
    // mysql_get_character_set_info(my, &charset_info);
    // printf("Character set name: %s\n", charset_info.name);
    // printf("Character set name: %s\n", mysql_character_set_name(my));

        // 循环的客户端
    // while (1)
    // {
    //     std::cout << "MYSQL > ";
    //     std::string tmp;
    //     if(!std::getline(std::cin, tmp) || tmp == "quit")
    //     {
    //         std::cout << "bye" << std::endl;
    //         break;    
    //     }

    //     int ret = mysql_query(my, tmp.c_str());
        
    //     if(MYSQL_RES* res = mysql_store_result(my))
    //     {
    //         int rows = mysql_num_rows(res);
    //         int fields = mysql_num_fields(res);
    //         std::cout << "row::" << rows << std::endl;
    //         std::cout << "fields::" << fields << std::endl;

    //         MYSQL_FIELD* fieldArr = mysql_fetch_fields(res);
    //         for(int j = 0; j < fields; ++j)
    //         {
    //             std::cout << fieldArr[j].name << '\t';
    //         }

    //         std::cout << std::endl;

    //         for(int i = 0; i < rows; ++i)
    //         {
    //             MYSQL_ROW rowArr = mysql_fetch_row(res);
    //             for(int j = 0; j < fields; ++j)
    //             {
    //                 std::cout << rowArr[j] << '\t';
    //             }
    //             std::cout << std::endl;
    //         }

    //         std::cout << "db:" << fieldArr[0].db << std::endl;
    //         std::cout << "table:" << fieldArr[0].table << std::endl;
    //         mysql_free_result(res);
    //     }

    //     if(ret == 0)
    //     {
    //         std::cout << "success" << std::endl;
    //     }
    //     else
    //     {
    //         std::cout << "err" << std::endl; 
    //     }
    // }
    

    return 0;
}

到此结束。。。

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

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

相关文章

Python (二) 读写excel文件

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一波电子书籍资料&#xff0c;包含《Effective Java中文版 第2版》《深入JAVA虚拟机》&#xff0c;《重构改善既有代码设计》&#xff0c;《MySQL高性能-第3版》&…

怎么把拍下来的实体印章公章转为透明电子章,并粘贴到word里面?

用word打开合同文档 插入公章图片&#xff08;jpg/png无所谓&#xff09; 右击图片→裁剪到你爽为止 右击图片→设置图片格式→高度和宽度设置为4厘米&#xff08;具体大小根据你的实际情况来&#xff09; 根据实际情况调整亮度和对比度 设置透明色 将印章衬于文字下方&#xf…

zxjy004- 子模块service及子子模块service_edu搭建

1、新建service module(maven工程&#xff0c;子模块) 1.1 右键 --> new moduel --->选择maven --->完成 1.2. 添加模块类型是 pom 2、引入项目需要的依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.…

springboot使用Validator参数校验

引用&#xff1a;https://www.cnblogs.com/yang-yz/p/17576507.html Validator校验框架遵循了 jsr-303验证规范(参数校验规范) JSR : java specification requests 为了解决开发人员在校验参数方面&#xff0c;少写代码 依赖&#xff1a; <dependency><groupId>o…

Navicat 与 华为云 GaussDB 合作再升级,赋能 GaussDB 分布式数据库

2023 年第三季度&#xff0c;Navicat 首次支持了华为云 GaussDB 主备版数据库。经过双方团队进一步的深化合作&#xff0c;Navicat 完成了 GaussDB 分布式的研发适配工作&#xff0c;赋能 GaussDB 全域数据库产品。 GaussDB 数据库分为主备版和分布式版两种模式。主备版适用于…

Java二阶知识点总结(一)Maven

一、Maven概念 Maven是一个项目管理工具&#xff0c;其主要作用有2点 依赖管理&#xff1a;管理项目依赖的各种jar包自动构建&#xff1a;项目构建的过程&#xff0c;从编译、测试、运行、打包到安装的过程可以一键执行 二、Maven工程的目录结构 src/main/java&#xff1a;…

三相电表可以当作高压电表使用吗?

在电力系统中&#xff0c;为了准确测量和计量电能的使用情况&#xff0c;电表起着至关重要的作用。与此同时&#xff0c;为了满足不同电网的需求&#xff0c;各种类型的电表被研发和设计出来。其中&#xff0c;三相电表作为常见的一种类型&#xff0c;广泛应用于低压电网中。但…

html刷题笔记

1 em 12 pt 16 px 100% source元素为audio、video、picture元素指定多个媒体文件 margin是用来隔开元素与元素的间距&#xff1b;padding是用来隔开元素与内容的间隔。 margin用于布局分开元素使元素与元素互不相干&#xff1b;padding用于元素与内容之间的间隔&#xff0c;…

js基础之事件监听案例入门

事件绑定 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </head&…

子查询在SQL中的应用和实践

作者&#xff1a;CSDN-川川菜鸟 在SQL中&#xff0c;子查询是一种强大的工具&#xff0c;用于解决复杂的数据查询问题。本文将深入探讨子查询的概念、类型、规则&#xff0c;并通过具体案例展示其在实际应用中的用途。 文章目录 子查询概念子查询的类型子查询的规则实际案例分析…

Live800:客服人员的压力来自于哪些方面?企业如何减轻客服压力?

客服人员是企业中非常重要的一支队伍&#xff0c;他们承担着与客户直接沟通的重要任务。然而&#xff0c;客服工作并不是一项轻松的工作&#xff0c;他们常常面临着各种各样的压力。那么&#xff0c;客服人员的压力究竟来自哪些方面&#xff1f;企业又应该如何减轻客服人员的压…

Slurm集群管理系统

Slurm集群管理系统 Slurm&#xff08;Simple Linux Utility for Resource Management&#xff0c;https://slurm.schedmd.com/&#xff09;是一个开源的、容错的、高度可扩展的集群管理和作业调度系统&#xff0c;适用于大型和小型高性能计算&#xff08;HPC&#xff09;集群。…

小团队是否值得购买企业网盘的策略分析

企业网盘的风越来越大&#xff0c;对于小团队而言&#xff0c;真的值得购入企业网盘吗&#xff1f;在购买企业服务之前&#xff0c;首先需要考虑的就是自身的需求。 您可以根据以下几个方面判断自己的团队是否真的需要购买企业网盘&#xff1f; 1、办公需求&#xff1a;企业网…

MES管理系统在生产计划排程中的应用与价值

随着制造业市场竞争的日益激烈和客户需求的多样化&#xff0c;传统的生产计划排程方式已经无法满足企业的需求。为了提升生产计划的效率和准确性&#xff0c;越来越多的企业开始引入MES管理系统这一先进的工具。那么&#xff0c;MES管理系统到底是什么&#xff0c;又是如何解决…

ES6之Map对象

ES6提供了 Map数据结构。它类似于对象&#xff0c;也是键值对的集合。但是“键”的范围不限于字符串&#xff0c;各种类型的值&#xff08;包括对象&#xff09;都可以当作键。 创建方法 let m new Map()console.log(m)Map的方法 1.set( ) 添加元素 接收两个参数&#xff0c…

Unity使用打成图集的Sprite作为模型贴图使用的问题

大家好&#xff0c;我是阿赵。   有时候用Unity引擎做项目的时候&#xff0c;会遇到这样的需求&#xff0c;美术做了一些模型或者特效&#xff0c;然后策划想在游戏运行的时候&#xff0c;读取一些游戏图标放在特效或者模型上面当做贴图使用。   这个需求实现起来很简单&am…

Vcenter 6.7 VCSA证书过期问题处理

1. 故障现象 2022年10月25日&#xff0c;登陆VC报错。 按照报错信息&#xff0c;结合官方文档&#xff0c;判断为STS证书过期导致。 vCenter Server Appliance (VCSA) 6.5.x, 6.7.x or vCenter Server 7.0.x 在/var/log/vmware/vpxd-svcs/vpxd-svcs.log看到类似报错: ERRO…

【面试题】 你知道怎么调试线上代码吗?

前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 这篇文章来分享下如何调试线上的代码 什么时候需要调试线上的代码呢&#xff0c;当线上代码出现 bug 的时候&#xff0c;需要定位问题&#xff0c;就需…

可视化监管云平台EasyCVR宠物粮食食品厂智能视频监控方案

由于我国养宠物群体的不断膨胀&#xff0c;宠物市场也占据了经济的很大一部分&#xff0c;宠物做为人类的好朋友&#xff0c;可以给人们带来极高的精神抚慰&#xff0c;作为“毛孩子”家长&#xff0c;爱宠人士自然不会亏待自家宠物&#xff0c;都会选择最好的口粮以供宠物食用…

Mysql主从集群搭建——基于docker-compose一键部署

搭建初衷 本身自己就是开发这类应用的工作者&#xff0c;一个私有库还是很有必要的。无论是公司项目还是私人项目都可以用到&#xff0c;不用担心忘记同步导致的数据丢失统一管理所有docker应用的数据&#xff08;如果容器可以连接mysql的话&#xff09;也方便随时修改数据结构…