Laravel 9中批量插入父子关联数据时将UUID替换为ID的实现方案
Laravel 9中批量插入父子关联数据时将UUID替换为ID的实现方案
嘿,我来帮你搞定这个批量插入关联数据时替换UUID为ID的问题!先看看你的表结构:
表结构
movies 表
| id | uuid | title | ... |
|---|---|---|---|
| 1 | uuid-m01 | movie 1 | ... |
categories 表
| id | uuid | title | ... |
|---|---|---|---|
| 1 | uuid-c01 | 动作片 | ... |
接下来我分场景给你讲具体实现方式,都是实战里常用的套路:
一对多关联场景(比如分类下的电影)
假设我们要批量插入分类,同时插入属于这些分类的电影,电影数据里用分类的UUID来关联,插入后要把电影的category_id替换成分类的实际自增ID。
步骤1:批量插入父表数据,建立UUID与ID的映射
首先插入分类数据,然后通过UUID查询出对应的ID,存成一个映射数组,方便后续替换:
// 准备要插入的分类数据,每条都带唯一UUID $categoryData = [ ['uuid' => 'uuid-c01', 'title' => '动作片', 'created_at' => now(), 'updated_at' => now()], ['uuid' => 'uuid-c02', 'title' => '喜剧片', 'created_at' => now(), 'updated_at' => now()], ]; // 批量插入分类 \App\Models\Category::insert($categoryData); // 生成UUID到ID的映射数组 $categoryUuidMap = \App\Models\Category::whereIn('uuid', collect($categoryData)->pluck('uuid')) ->pluck('id', 'uuid') ->toArray();
步骤2:处理子表数据,替换UUID为ID
接着把原始的电影数据里的分类UUID替换成对应的ID,再批量插入:
// 原始电影数据,用分类UUID关联 $movieData = [ ['uuid' => 'uuid-m01', 'title' => '头号玩家', 'category_uuid' => 'uuid-c01', 'created_at' => now(), 'updated_at' => now()], ['uuid' => 'uuid-m02', 'title' => '夏洛特烦恼', 'category_uuid' => 'uuid-c02', 'created_at' => now(), 'updated_at' => now()], ]; // 转换数据:把category_uuid替换成category_id $processedMovieData = collect($movieData)->map(function ($movie) use ($categoryUuidMap) { return [ 'uuid' => $movie['uuid'], 'title' => $movie['title'], 'category_id' => $categoryUuidMap[$movie['category_uuid']], 'created_at' => $movie['created_at'], 'updated_at' => $movie['updated_at'], ]; })->toArray(); // 批量插入电影 \App\Models\Movie::insert($processedMovieData);
步骤3:加上事务保证数据一致性
为了避免插入过程中出现错误导致数据不一致,最好把所有操作放在事务里:
\DB::beginTransaction(); try { // 插入分类并生成映射 \App\Models\Category::insert($categoryData); $categoryUuidMap = \App\Models\Category::whereIn('uuid', collect($categoryData)->pluck('uuid')) ->pluck('id', 'uuid') ->toArray(); // 处理并插入电影 $processedMovieData = collect($movieData)->map(function ($movie) use ($categoryUuidMap) { return [ 'uuid' => $movie['uuid'], 'title' => $movie['title'], 'category_id' => $categoryUuidMap[$movie['category_uuid']], 'created_at' => $movie['created_at'], 'updated_at' => $movie['updated_at'], ]; })->toArray(); \App\Models\Movie::insert($processedMovieData); \DB::commit(); } catch (\Exception $e) { \DB::rollBack(); // 这里可以根据需求处理错误,比如返回错误提示 throw $e; }
多对多关联场景(比如电影属于多个分类)
如果是多对多关系(有中间表movie_category),思路差不多,只是需要同时处理两个表的UUID映射:
- 先插入分类和电影,分别生成UUID到ID的映射
- 处理中间表数据,把电影UUID和分类UUID都替换成对应的ID
- 批量插入中间表数据
核心逻辑和一对多一致,只是多了一层映射处理,这里就不贴重复代码啦。
几个注意点
- 确保你的
uuid字段在表中是唯一索引,这样查询映射时不会出现重复ID的问题 - 如果插入的数据量特别大,
whereIn里的UUID数量别超过数据库限制,可以分成多批处理 - 如果你用的是Laravel的
insertGetId,它只会返回第一条插入记录的ID,所以用insert后再查询映射是更可靠的方式
备注:内容来源于stack exchange,提问作者Mr.Singh
相关产品推荐
相关产品推荐

