当前位置: 首页 > news >正文

hyperf 二十六 数据迁移 二

教程:Hyperf

参考文章hyperf 二十五 数据迁移 一-CSDN博客

根据之前写的数据迁移的文章,已经说明Hyperf\Database\Schema\Schema::create()实际运行Hyperf\Database\Schema\Grammars\MySqlGrammar::compileCreate()生成的sql字符串。

文档所谓"在迁移文件中主要通过 Hyperf\Database\Schema\Schema 类来定义数据表和管理迁移流程。",就是使用Schema来执行具体的迁移sql。生成迁移sql的内容由回调设置。

一 数据表

1.1 创建数据表

使用Hyperf\Database\Schema\Blueprint类对象设置表结构。

属性解释类型

engine

指定表存储引擎string

charset

指定表默认字符集string

collation

指定表默认排序规则string

temporary

指定是否为临时表boolen

after

在该列之后添加新列string

Blueprint::temporary()设置temporary为true,设置为临时表。

1.2 重命名数据表

可以使用 $table->rename($to),或者Schema::rename($from,$to)。

 1.2.1 $table->rename($to)

Blueprint::rename($to)重命名表名,$to为重新定义的表名。

执行的是Blueprint::rename(),其将执行内容设置为Hyperf\Utils\Fluent类的name属性,并将其放到数组commands中,之后获取sql时调用Blueprint::toSql()。

Blueprint::toSql()遍历数组commands,执行以compile开头的Hyperf\Database\Schema\Grammars\Grammar或其子类的对应方法。

1.2.2 Schema::rename($from, $to)

Hyperf\Database\Schema\Schema::__callStatic()获取对应驱动的Connection子类,再获取Builder或其子类执行对应方法。

以musql驱动为例,$table->rename($to)执行Hyperf\Database\Schema\Blueprint::rename($to),Schema::rename($from,$to)通过子类Hyperf\Database\Schema\MySqlBuilder执行Hyperf\Database\Schema\Builder::rename($from,$to)。

Builder::rename($from,$to)中调用Builder::createBlueprint(),返回Hyperf\Database\Schema\Blueprint类对象。即Schema::rename($from,$to)其实最后也是执行Blueprint类方法。

使用Blueprint需要在回调当中使用。根据源码Schema::table()中可以设置回调。

注:在重命名表之前,应判断该表是否为其他表外键。

1.3 删除数据表

在删除表之前应判断表是否存在。

1.3.1 删除表

使用Schema::drop($table),或者$table::drop()。

根据以上逻辑,$table::drop()执行Hyperf\Database\Schema\Blueprint::drop(),Schema::drop($table)执行Hyperf\Database\Schema\Builder::drop($table)。

Builder::drop($table)中也调用Builder::createBlueprint()。

1.3.2 判断表是否存在

使用Schema::dropIfExists($table),或者$table::dropIfExists()。

根据以上逻辑,$table::drop()执行Hyperf\Database\Schema\Blueprint::dropIfExists(),Schema::drop($table)执行Hyperf\Database\Schema\Builder::dropIfExists($table)。

Builder::dropIfExists($table)中也调用Builder::createBlueprint()。

1.3.3 检查表是否存在

使用Schema::hasTable($table),执行Hyperf\Database\Schema\Builder::hasTable($table)。

Schema\Builder::hasTable($table)直接执行Hyperf\Database\Schema\Grammars\Grammar或其子类compileTableExists()返回的sql字符串。

1.3.4 检查字段是否存在

使用Schema::hasColumn($table, $column),执行Hyperf\Database\Schema\Builder::hasColumn($table, $column)。也是直接执行查询出列名,再用in_array()做判断。

1.4 数据库链接选项

设置connection属性,其值为数据库配置文件中数组最外层key值。

为多个数据库连接设置对应配置……这样根据之前文章的修改内容就不用改了……

这里的内容,若迁移使用不同数据库配置,而且不修改源码的情况下,需要在前文件中设置连接。

这样确实安全点……但是执行迁移时,参数中--database会无效而且还不能回滚,除非设置成和命令一样的表。

/(ㄒoㄒ)/~~ 还是一次性看完比较好,当时就想到会有这样的设计,但是感觉不太合理。

二 字段

2.1 创建字段

可用字段定义方法

$table->bigIncrements('id');递增 ID(主键),相当于「UNSIGNED BIG INTEGER」
$table->bigInteger('votes');相当于 BIGINT
$table->binary('data');相当于 BLOB
$table->boolean('confirmed');相当于 BOOLEAN
$table->char('name', 100);相当于带有长度的 CHAR
$table->date('created_at');相当于 DATE
$table->dateTime('created_at');相当于 DATETIME
$table->dateTimeTz('created_at');相当于带时区 DATETIME
$table->decimal('amount', 8, 2);相当于带有精度与基数 DECIMAL
$table->double('amount', 8, 2);相当于带有精度与基数 DOUBLE
$table->enum('level', ['easy', 'hard']);相当于 ENUM
$table->float('amount', 8, 2);相当于带有精度与基数 FLOAT
$table->geometry('positions');相当于 GEOMETRY
$table->geometryCollection('positions');相当于 GEOMETRYCOLLECTION
$table->increments('id');递增的 ID (主键),相当于「UNSIGNED INTEGER」
$table->integer('votes');相当于 INTEGER
$table->ipAddress('visitor');相当于 IP 地址
$table->json('options');相当于 JSON
$table->jsonb('options');相当于 JSONB
$table->lineString('positions');相当于 LINESTRING
$table->longText('description');相当于 LONGTEXT
$table->macAddress('device');相当于 MAC 地址
$table->mediumIncrements('id');递增 ID (主键) ,相当于「UNSIGNED MEDIUM INTEGER」
$table->mediumInteger('votes');相当于 MEDIUMINT
$table->mediumText('description');相当于 MEDIUMTEXT
$table->morphs('taggable');相当于加入递增的 taggable_id 与字符串 taggable_type
$table->multiLineString('positions');相当于 MULTILINESTRING
$table->multiPoint('positions');相当于 MULTIPOINT
$table->multiPolygon('positions');相当于 MULTIPOLYGON
$table->nullableMorphs('taggable');相当于可空版本的 morphs() 字段
$table->nullableTimestamps();相当于可空版本的 timestamps() 字段
$table->point('position');相当于 POINT
$table->polygon('positions');相当于 POLYGON
$table->rememberToken();相当于可空版本的 VARCHAR (100) 的 remember_token 字段
$table->smallIncrements('id');递增 ID (主键) ,相当于「UNSIGNED SMALL INTEGER」
$table->smallInteger('votes');相当于 SMALLINT
$table->softDeletes();相当于为软删除添加一个可空的 deleted_at 字段
$table->softDeletesTz();相当于为软删除添加一个可空的 带时区的 deleted_at 字段
$table->string('name', 100);相当于带长度的 VARCHAR
$table->text('description');相当于 TEXT
$table->time('sunrise');相当于 TIME
$table->timeTz('sunrise');相当于带时区的 TIME
$table->timestamp('added_on');相当于 TIMESTAMP
$table->timestampTz('added_on');相当于带时区的 TIMESTAMP
$table->timestamps();相当于可空的 created_at 和 updated_at TIMESTAMP
$table->timestampsTz();相当于可空且带时区的 created_at 和 updated_at TIMESTAMP
$table->tinyIncrements('id');相当于自动递增 UNSIGNED TINYINT
$table->tinyInteger('votes');相当于 TINYINT
$table->unsignedBigInteger('votes');相当于 Unsigned BIGINT
$table->unsignedDecimal('amount', 8, 2);相当于带有精度和基数的 UNSIGNED DECIMAL
$table->unsignedInteger('votes');相当于 Unsigned INT
$table->unsignedMediumInteger('votes');相当于 Unsigned MEDIUMINT
$table->unsignedSmallInteger('votes');相当于 Unsigned SMALLINT
$table->unsignedTinyInteger('votes');相当于 Unsigned TINYINT
$table->uuid('id');相当于 UUID
$table->year('birth_year');相当于 YEAR
$table->comment('Table Comment');设置表注释,相当于 COMMENT

 大概运行都是Grammar或其子类,简称为Grammar类。运行Grammar类方法compileAdd(),Grammar::compileAdd()中运行Grammar::getType(),调用以type开头的Grammar类对应方法,用于返回sql字符串。

2.2 修改字段

composer require "doctrine/dbal:^3.0"

 根据文档

Schema::table('users', function (Blueprint $table) {// 将字段的长度修改为 50 并允许为空$table->string('name', 50)->nullable()->change();
});

$table->string()返回\Hyperf\Database\Schema\ColumnDefinition类对象。ColumnDefinition父类Hyperf\Utils\Fluent::__call()实际执行nullable()和change()。

Fluent::__call()返回$this,所以用“->”继续调用。其仅设置以方法名设置的属性值。

Hyperf\Database\Schema\Blueprint::toSql()时使用对应属性,具体执行Hyperf\Database\Schema\Grammars\Grammar::compileChange(),最终执行Doctrine\DBAL\Platforms\AbstractMySQLPlatform::getAlterTableSQL()。

所以必须安装doctrine/dbal。

只有下面的字段类型能被 "修改": bigInteger、 binary、 boolean、date、dateTime、dateTimeTz、decimal、integer、json、 longText、mediumText、smallInteger、string、text、time、 unsignedBigInteger、unsignedInteger and unsignedSmallInteger。

2.3 重命名字段

$table->renameColumn('from', 'to')->change();

执行Hyperf\Database\Schema\Grammars\Grammar::compileRenameColumn(),然后执行Hyperf\Database\Schema\Grammars\RenameColumn::compile(),最后也是执行Doctrine\DBAL\Platforms\AbstractMySQLPlatform::getAlterTableSQL()。

2.4 删除字段

$table->dropColumn('name');$table->dropColumn(['name', 'age']);

根据以上逻辑执行Hyperf\Database\Schema\Grammars\Grammar:compileDropColumn(),直接生成sql字符串。

三 测试

3.1 表

测试流程

  1. 创建表
  2. 重命名表
  3. 删除表

3.1.1 创建表

use test1;
show tables;

 

php bin/hyperf gen:migration create_test_table
#migrations\2024_03_06_082623_create_userinfo_table.php
class CreateUserinfoTable extends Migration {protected $connection = 'default2';/*** Run the migrations.*/public function up(): void {Schema::create('userinfo', function (Blueprint $table) {$table->bigIncrements('id');$table->timestamps();});}/*** Reverse the migrations.*/public function down(): void {Schema::dropIfExists('userinfo');}
}
#migrations\2024_03_11_070103_create_test_table.php
class CreateTestTable extends Migration {protected $connection = 'default2';/*** Run the migrations.*/public function up(): void {Schema::create('test', function (Blueprint $table) {$table->bigIncrements('id');$table->timestamps();$table->engine = 'MyISAM';// 指定数据表的默认字符集$table->charset = 'utf8mb4';// 指定数据表默认的排序规则$table->collation = 'utf8mb4_unicode_ci';// 创建临时表$table->temporary();});}/*** Reverse the migrations.*/public function down(): void {Schema::dropIfExists('test');}
}
php bin/hyperf.php   migrate --database=default2
Migrating: 2024_03_06_082623_create_userinfo_table
Migrated:  2024_03_06_082623_create_userinfo_table
Migrating: 2024_03_11_070103_create_test_table
Migrated:  2024_03_11_070103_create_test_table

 

 migration中有test表的记录,但是实际库中没有test表。可能和设置为临时表有关。

经查询mysql临时表仅在当前会话(session)中有效,会话结束时自动消失。

所以把临时表去掉再试下,但是记录未删除的话不会执行。

再次执行,从数据库表看,执行正常。

 3.1.2 重命名表

php bin/hyperf.php gen:migration update_test_table --table=test[INFO] Created Migration: 2024_03_11_074311_update_test_table
#migrations\2024_03_11_074311_update_test_table.php
class UpdateTestTable extends Migration {protected $connection = 'default2';/*** Run the migrations.*/public function up(): void {Schema::table('test', function (Blueprint $table) {$table->rename("test1");});}/*** Reverse the migrations.*/public function down(): void {Schema::table('test', function (Blueprint $table) {//});}
}
php bin/hyperf.php   migrate --database=default2Migrating: 2024_03_11_074311_update_test_table
Migrated:  2024_03_11_074311_update_test_table

  3.1.3 删除表

php bin/hyperf.php gen:migration update_test2_table --table=test[INFO] Created Migration:2024_03_11_075322_update_test2_table.php

因为down函数仅在回滚时执行,所以在up()中设置表删除。

#migrations\2024_03_11_075322_update_test2_table.php
class UpdateTest2Table extends Migration {protected $connection = 'default2';/*** Run the migrations.*/public function up(): void {Schema::table('test1', function (Blueprint $table) {$table->dropIfExists();});}/*** Reverse the migrations.*/public function down(): void {Schema::table('test1', function (Blueprint $table) {//});}
}
php bin/hyperf.php   migrate --database=default2Migrating: 2024_03_11_075322_update_test2_table
Migrated:  2024_03_11_075322_update_test2_table

3.2 字段

测试流程

  1. 设置字段
  2. 修改字段
  3. 删除字段

3.2.1 设置字段

php bin/hyperf.php gen:migration update_userinfo_table --table=userinfo[INFO] Created Migration: 2024_03_11_080602_update_userinfo_table
#migrations\2024_03_11_080602_update_userinfo_table.php
class UpdateUserinfoTable extends Migration {protected $connection = 'default2';/*** Run the migrations.*/public function up(): void {Schema::table('userinfo', function (Blueprint $table) {$table->string('name', 255);$table->tinyInteger('age');});}/*** Reverse the migrations.*/public function down(): void {Schema::table('userinfo', function (Blueprint $table) {//});}
}
php bin/hyperf.php   migrate --database=default2Migrating: 2024_03_11_080602_update_userinfo_table
Migrated:  2024_03_11_080602_update_userinfo_table
DESCRIBE userinfo;

3.2.2 修改字段

php bin/hyperf.php gen:migration update_userinfo2_table --table=userinfo[INFO] Created Migration: 2024_03_11_081819_update_userinfo2_table
#migrations\2024_03_11_081819_update_userinfo2_table.php
class UpdateUserinfo2Table extends Migration {protected $connection = 'default2';/*** Run the migrations.*/public function up(): void {Schema::table('userinfo', function (Blueprint $table) {$table->string("name")->nullable()->change();$table->renameColumn('age', 'age1')->nullable()->change();});}/*** Reverse the migrations.*/public function down(): void {Schema::table('userinfo', function (Blueprint $table) {//});}
}
php bin/hyperf.php   migrate --database=default2Migrating: 2024_03_11_081819_update_userinfo2_table
Migrated:  2024_03_11_081819_update_userinfo2_table
DESCRIBE userinfo;

执行回滚,然会修改文件再次执行。

php bin/hyperf.php migrate:rollback --database=default2Rolling back: 2024_03_11_081819_update_userinfo2_table
Rolled back:  2024_03_11_081819_update_userinfo2_table

但是数据库字段没变……因为down里没设置语句……

#migrations\2024_03_11_081819_update_userinfo2_table.php
class UpdateUserinfo2Table extends Migration {protected $connection = 'default2';/*** Run the migrations.*/public function up(): void {Schema::table('userinfo', function (Blueprint $table) {$table->string("name")->nullable()->change();//$table->tinyInteger('age')->nullable()->change();});}/*** Reverse the migrations.*/public function down(): void {Schema::table('userinfo', function (Blueprint $table) {$table->string("name")->change();$table->tinyInteger('age')->change();});}
}

经过手动改动后,此时数据表结构:

 测试时用$table->tinyInteger('age')测试修改,确实报错PHP Fatal error:  Uncaught Doctrine\DBAL\Exception: Unknown column type "tinyinteger" requested. Any Doctrine type that you use has to be registered with \Doctrine\DBAL\Types\Type::addType().

因为这种字段类型不能修改。所以将代码改为上面图中内容,再次执行。

php bin/hyperf.php   migrate --database=default2Migrating: 2024_03_11_081819_update_userinfo2_table
Migrated:  2024_03_11_081819_update_userinfo2_table

 测试发现写notnull无效,因为改前和改后表差异对比时返回false,但是Hyperf\Utils\Fluent属性notnull确实设置为true。

对应源码

#Hyperf\Database\Schema\Grammars\ChangeColumn
public static function compile($grammar, Blueprint $blueprint, Fluent $command, Connection $connection) {if (!$connection->isDoctrineAvailable()) {throw new RuntimeException(sprintf('Changing columns for table "%s" requires Doctrine DBAL; install "doctrine/dbal".',$blueprint->getTable()));}$tableDiff = static::getChangedDiff($grammar,$blueprint,$schema = $connection->getDoctrineSchemaManager());if ($tableDiff !== false) {return (array) $schema->getDatabasePlatform()->getAlterTableSQL($tableDiff);}return [];}#$tableDiff 为false
#Hyperf\Database\Schema\Grammars\ChangeColumn
protected static function getTableWithColumnChanges(Blueprint $blueprint, Table $table) {$table = clone $table;foreach ($blueprint->getChangedColumns() as $fluent) {$column = static::getDoctrineColumn($table, $fluent);// Here we will spin through each fluent column definition and map it to the proper// Doctrine column definitions - which is necessary because Laravel and Doctrine// use some different terminology for various column attributes on the tables.foreach ($fluent->getAttributes() as $key => $value) {if (!is_null($option = static::mapFluentOptionToDoctrine($key))) {if (method_exists($column, $method = 'set' . ucfirst($option))) {$column->{$method}(static::mapFluentValueToDoctrine($option, $value));}}}}return $table;}protected static function getTableWithColumnChanges(Blueprint $blueprint, Table $table) {$table = clone $table;foreach ($blueprint->getChangedColumns() as $fluent) {$column = static::getDoctrineColumn($table, $fluent);// Here we will spin through each fluent column definition and map it to the proper// Doctrine column definitions - which is necessary because Laravel and Doctrine// use some different terminology for various column attributes on the tables.foreach ($fluent->getAttributes() as $key => $value) {if (!is_null($option = static::mapFluentOptionToDoctrine($key))) {if (method_exists($column, $method = 'set' . ucfirst($option))) {$column->{$method}(static::mapFluentValueToDoctrine($option, $value));}}}}return $table;}#column 
/***
object(Doctrine\DBAL\Schema\Column)#901 (16) {["_type":protected]=>object(Doctrine\DBAL\Types\StringType)#884 (0) {}["_length":protected]=>int(255)["_precision":protected]=>int(10)["_scale":protected]=>int(0)["_unsigned":protected]=>bool(false)["_fixed":protected]=>bool(false)["_notnull":protected]=>bool(false)["_default":protected]=>NULL["_autoincrement":protected]=>bool(false)["_platformOptions":protected]=>array(2) {["charset"]=>string(7) "utf8mb4"["collation"]=>string(18) "utf8mb4_unicode_ci"}["_columnDefinition":protected]=>NULL["_comment":protected]=>NULL["_customSchemaOptions":protected]=>array(0) {}["_name":protected]=>string(4) "name"["_namespace":protected]=>NULL["_quoted":protected]=>bool(false)
}
***/#$fluent
/***
array(5) {["type"]=>string(6) "string"["name"]=>string(4) "name"["length"]=>int(255)["notnull"]=>bool(true)["change"]=>bool(true)
}
***/
#Hyperf\Database\Schema\Grammars\ChangeColumn
protected static function mapFluentOptionToDoctrine($attribute) {switch ($attribute) {case 'type':case 'name':return;case 'nullable':return 'notnull';case 'total':return 'precision';case 'places':return 'scale';default:return $attribute;}}
#Hyperf\Utils\Fluent
public function __call($method, $parameters){$this->attributes[$method] = count($parameters) > 0 ? $parameters[0] : true;return $this;}
#Doctrine\DBAL\Schema\Column
/** @return mixed[] */public function toArray(){return array_merge(['name'          => $this->_name,'type'          => $this->_type,'default'       => $this->_default,'notnull'       => $this->_notnull,'length'        => $this->_length,'precision'     => $this->_precision,'scale'         => $this->_scale,'fixed'         => $this->_fixed,'unsigned'      => $this->_unsigned,'autoincrement' => $this->_autoincrement,'columnDefinition' => $this->_columnDefinition,'comment' => $this->_comment,], $this->_platformOptions, $this->_customSchemaOptions);}
#Doctrine\DBAL\Platforms\DB2Platform
private function getAlterColumnClausesSQL(ColumnDiff $columnDiff): array{$newColumn = $columnDiff->getNewColumn()->toArray();$alterClause = 'ALTER COLUMN ' . $columnDiff->getNewColumn()->getQuotedName($this);if ($newColumn['columnDefinition'] !== null) {return [$alterClause . ' ' . $newColumn['columnDefinition']];}……
}

 

根据源码意思,应该是看Doctrine\DBAL\Schema\Column类中是否有对应的set方法。果然Column类中没有setNotnull(),仅有setNullable()。所以能用的就是Column类中以set开头的方法。

方法调用解释
Column::setType()type()字段类型
Column::setNamename()字段名
Column::setLength()length()字段长度

Column::setPrecision()

total()或者precision()

字段浮点精度

setScale()

places()或者scale()小数点后位数

setUnsigned()

unsigned()无符号

setFixed()

fixed()双精度浮点

setNotnull()

notnull()设置是否不为空

setDefault()

default()设置默认值

setPlatformOptions()

platformOptions()批量设置其他属性

setPlatformOption()

platformOption()单个设置其他属性

setColumnDefinition()

columnDefinition()大概是直接定义的语句

 

应该notnull这样的属性没被处理。 结合属性的定义,可以尝试传参数。比如nullable(false)。

执行代码改为

#migrations\2024_03_11_081819_update_userinfo2_table.php
class UpdateUserinfo2Table extends Migration {protected $connection = 'default2';/*** Run the migrations.*/public function up(): void {Schema::table('userinfo', function (Blueprint $table) {$table->string("name")->nullable(false)->change();//$table->tinyInteger('age')->nullable()->change();});}/*** Reverse the migrations.*/public function down(): void {Schema::table('userinfo', function (Blueprint $table) {$table->string("name")->change();$table->tinyInteger('age')->change();});}
}
php bin/hyperf.php   migrate --database=default2Migrating: 2024_03_11_081819_update_userinfo2_table
Migrated:  2024_03_11_081819_update_userinfo2_table

修改成功

3.2.3 删除字段

php bin/hyperf.php gen:migration update_userinfo3_table --table=userinfo[INFO] Created Migration: 2024_03_11_094726_update_userinfo3_table
#migrations\2024_03_11_094726_update_userinfo3_table.php
class UpdateUserinfo3Table extends Migration {protected $connection = 'default2';/*** Run the migrations.*/public function up(): void {Schema::table('userinfo', function (Blueprint $table) {$table->dropColumn(['name', 'age']);});}/*** Reverse the migrations.*/public function down(): void {Schema::table('userinfo', function (Blueprint $table) {//});}
}
php bin/hyperf.php   migrate --database=default2Migrating: 2024_03_11_094726_update_userinfo3_table
Migrated:  2024_03_11_094726_update_userinfo3_table
DESCRIBE userinfo

相关文章:

hyperf 二十六 数据迁移 二

教程:Hyperf 参考文章hyperf 二十五 数据迁移 一-CSDN博客 根据之前写的数据迁移的文章,已经说明Hyperf\Database\Schema\Schema::create()实际运行Hyperf\Database\Schema\Grammars\MySqlGrammar::compileCreate()生成的sql字符串。 文档所谓"在…...

linux下如何hook第三方播放器的视频数据?

背景 作为显卡生产商,当用户使用我们的显卡硬解码播放视频时,如果出现比如花屏等问题,为了快速确定问题原因,我们需要一个工具来帮助判断出问题是出在原始视频端,亦或者是应用程序端,亦或者是显卡端。因此我们需要一种方法,来对目标播放器程序进行监控,并捕获到视频源的…...

如何通过Python代码连接OceanBase Oracle租户

背景 目前,连接数据库的Oracle租户,只能通过Java和C的驱动程序,无法通过其他语言的驱动程序。为了满足社区中用户希望在Python代码中连接Oracle租户的需求,这里提供一种替代方案。通过结合使用JayDeBeApi和JDBC,我们可…...

2 月 Web3 游戏行业动态

作者:stellafootprint.network 数据来源:区块链游戏研究页面 - Footprint Analytics 2024 年 2 月,区块链游戏领域在加密货币价格上涨和活跃用户激增的推动下,实现了显著增长。然而,行业在维持用户参与度和留存率方面…...

普发Pfeiffer Prisma QMS200四极质谱计内部电路图装配3D图电路板接口详细注解

普发Pfeiffer Prisma QMS200四极质谱计内部电路图装配3D图电路板接口详细注解...

2024.03.04——2024.03.10 力扣练习总结及专项巩固(二)

1. (22. 括号生成&#xff09;这里只讨论第二种做法回溯法。在回溯法的函数void backtrack(vector<string>& ans, string& current, int open, int close, int n); 中&#xff0c;可分为三个if条件判断&#xff0c;分别判断当current.size() 2*n&#xff0c;ope…...

前端NodeJs笔记之包结构到进程和线程到命令行到Node模块化讲解

包结构 包实际上是一个压缩文件&#xff0c;解压以后还原为目录&#xff0c;符合规范的目录应该包含如下文件&#xff1a; ​ -package.json 描述文件 ​ -bin 可执行二进制文件 ​ -lib js代码 ​ -doc …...

【Java】获取手机文件名称补充

本地的 ADB 工具路径指的是你电脑上安装的 Android Debug Bridge&#xff08;ADB&#xff09;工具的路径。ADB 是 Android SDK 中的一个工具&#xff0c;用于与连接到计算机上的 Android 设备进行通信。你需要确保 ADB 已正确安装&#xff0c;并知道其在你计算机上的位置。 通…...

YoloV8改进策略:BackBone改进|TransNeXt:ViT的鲁棒Foveal视觉感知

文章目录 摘要论文:《TransNeXt:ViT的鲁棒Foveal视觉感知》1、引言2、相关工作3、方法3.1、聚合像素焦点注意力3.1.1、像素焦点注意力3.1.2、在单个混合器中聚合不同的注意力3.1.3、克服多尺度图像输入3.1.4、特征分析3.2、卷积门控单元(Convolutional GLU)3.2.1、动机3.2.…...

三维的旋转平移矩阵形式

在三维空间中&#xff0c;一个物体或坐标系的旋转和平移可以通过一个4x4的变换矩阵来表示。这个矩阵通常被称为仿射变换矩阵或齐次变换矩阵。它结合了旋转矩阵和平移向量的功能&#xff0c;能够同时表示旋转和平移操作。 一个4x4的旋转平移矩阵通常具有以下形式&#xff1a; 复…...

ChatGPT+MATLAB应用

MatGPT是一个由chatGPT类支持的MATLAB应用程序&#xff0c;由官方Toshiaki Takeuchi开发&#xff0c;允许您轻松访问OpenAI提供的chatGPT API。作为官方发布的内容&#xff0c;可靠性较高&#xff0c;而且也是完全免费开源的&#xff0c;全程自己配置&#xff0c;无需注册码或用…...

C语言—冒泡排序

C语言—冒泡排序 原理过程讲解代码1、直接在主函数里面实现2、编写函数进行实现 原理 冒泡排序的原理是&#xff1a;从左到右&#xff0c;相邻元素进行比较。每次比较一轮&#xff0c;就会找到序列中最大的一个或最小的一个。这个数就会从序列的最右边冒出来。 以从小到大排序…...

Discord OAuth2授权以及机器人监听群事件

下面文章讲解获取OAuth2授权整个流程&#xff0c;创建机器人&#xff0c;使用机器人监听工会&#xff08;工会就是创建的服务器&#xff09;成员变化等等&#xff0c;对接国外的都是需要VPN的哦&#xff0c;对接的时候记得提前准备。 创建应用 点击 此页面添加应用,&#xff…...

微信小程序返回上一页刷新组件数据

在父页面的onShow和onHide里面添加一个标志 onShow() {this.setData({show:true})},onHide() {this.setData({show:false})}, 把这个值传给子组件 <importantList slot"importantConcern" flag"{{barSelect}}" flag2"{{show}}" /> 在子组…...

Aging Cell:匈牙利学者发现肠道微生物组的变化和衰老密切相关

基于DNA甲基化衰老时钟的开发可以准确用来测量生物年龄&#xff0c;生物年龄在很大程度上受生活方式、环境和遗传等因素的影响&#xff0c;大量证据也表明健康生活方式可以延缓衰老并延长寿命。 先前大规模微生物组分析表明&#xff0c;随着年龄的增长&#xff0c;微生物组菌群…...

837. 连通块中点的数量(acwing)

文章目录 837. 连通块中点的数量题目描述维护size的并查集 837. 连通块中点的数量 题目描述 给定一个包含 n 个点&#xff08;编号为 1&#xff5e;n&#xff09;的无向图&#xff0c;初始时图中没有边。 现在要进行 m 个操作&#xff0c;操作共有三种&#xff1a; C a b&a…...

【wine】WINEDEBUG 分析mame模拟器不能加载roms下面的游戏 可以调整参数,快速启动其中一个游戏kof98

故障现象&#xff0c;MAME启动后&#xff0c;游戏都没有识别 添加日志输出&#xff0c;重新启动wine #!/bin/bashexport WINEPREFIX$(pwd)/.wine export WINESERVER$(pwd)/bin/wineserver export WINELOADER$(pwd)/bin/wine export WINEDEBUG"file,mame,warn,err"…...

pytorch安装记录

pytorch安装记录 1 安装anconda2 安装pycharm3 安装显卡驱动4 根据显卡驱动版本下载CUDA5 cudnn安装6 根据CUDA版本安装pytorch7 pytorch卸载 1 安装anconda 下载地址: https://www.anaconda.com/download#downloads 验证是否安装成功&#xff1a;打开cmd, 输入 conda 验证环…...

不依赖第三方平台,用Dart语言实现 ios 消息推送

仅仅给大家提供代码,还搞不定的欢迎咨询。 void _sendIosPushNotification(BleMessage message, String deviceToken, {bool debugMode = false}) async {final Map<String, dynamic> header = {"alg": "ES256", "kid": GloabelConfigu…...

TEASEL: A transformer-based speech-prefixed language model

文章目录 TEASEL&#xff1a;一种基于Transformer的语音前缀语言模型文章信息研究目的研究内容研究方法1.总体框图2.BERT-style Language Models&#xff08;基准模型&#xff09;3.Speech Module3.1Speech Temporal Encoder3.2Lightweight Attentive Aggregation (LAA) 4.训练…...

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇&#xff0c;在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下&#xff1a; 【Note】&#xff1a;如果你已经完成安装等操作&#xff0c;可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作&#xff0c;重…...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

【Java学习笔记】Arrays类

Arrays 类 1. 导入包&#xff1a;import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序&#xff08;自然排序和定制排序&#xff09;Arrays.binarySearch()通过二分搜索法进行查找&#xff08;前提&#xff1a;数组是…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

MySQL账号权限管理指南:安全创建账户与精细授权技巧

在MySQL数据库管理中&#xff0c;合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号&#xff1f; 最小权限原则&#xf…...

【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制

使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下&#xff0c;限制某个 IP 的访问频率是非常重要的&#xff0c;可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案&#xff0c;使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...