当前位置: 首页 > 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.训练…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...

Mobile ALOHA全身模仿学习

一、题目 Mobile ALOHA&#xff1a;通过低成本全身远程操作学习双手移动操作 传统模仿学习&#xff08;Imitation Learning&#xff09;缺点&#xff1a;聚焦与桌面操作&#xff0c;缺乏通用任务所需的移动性和灵活性 本论文优点&#xff1a;&#xff08;1&#xff09;在ALOHA…...

React从基础入门到高级实战:React 实战项目 - 项目五:微前端与模块化架构

React 实战项目&#xff1a;微前端与模块化架构 欢迎来到 React 开发教程专栏 的第 30 篇&#xff01;在前 29 篇文章中&#xff0c;我们从 React 的基础概念逐步深入到高级技巧&#xff0c;涵盖了组件设计、状态管理、路由配置、性能优化和企业级应用等核心内容。这一次&…...