[英]Laravel inserting parent child fails inside transaction
我正在尝试执行 2 次插入,在 2 个表中,表受外键约束。 这两个操作必须在事务中执行以防止最终失败。 (实际上我需要在更多表上执行更多插入,因此事务很重要;但本例中的 2 个表足以复制问题)
数据库驱动是pgsql
SomeRepo.php (也尝试使用事务关闭变体)
DB::beginTransaction();
try {
$parentData = [
'name' => 'Parent name'
];
$parent = new Parent($parentData);
$parent->save();
$childData = [
// Tried it with and without setting "parent_id" here
'parent_id' => $parent->id,
'name' => 'Child name'
];
$child = new Child($childData);
$parent->children()->save($child);
DB::commit();
} catch (Exception $e) {
DB::rollback();
}
父.php
protected $fillable = [
'name'
];
public function children()
{
return $this->hasMany(Child::class);
}
Child.php
protected $fillable = [
'name', 'parent_id'
];
尝试插入子行时执行失败,返回父 ID。
insert or update on table "child" violates foreign key constraint "child_parent_id_foreign"
编辑子表 SQL:
DROP TABLE IF EXISTS "public"."child";
CREATE TABLE "public"."child" (
"id" int4 NOT NULL DEFAULT nextval('child_id_seq'::regclass),
"parent_id" int4 NOT NULL,
"is_read" bool NOT NULL DEFAULT false,
"created_at" timestamp(0) DEFAULT now(),
"updated_at" timestamp(0),
"deleted_at" timestamp(0)
)
;
ALTER TABLE "public"."child" OWNER TO "my_user";
-- ----------------------------
-- Primary Key structure for table child
-- ----------------------------
ALTER TABLE "public"."child" ADD CONSTRAINT "child_pkey" PRIMARY KEY ("id");
-- ----------------------------
-- Foreign Keys structure for table child
-- ----------------------------
ALTER TABLE "public"."child" ADD CONSTRAINT "child_parent_id_fkey" FOREIGN KEY ("parent_id") REFERENCES "public"."parent" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION DEFERRABLE INITIALLY DEFERRED;
要将数据保存在相关表中,请使用此
Parent::create(['name'=>'parent name']); //save in parent table
$lastId = Parent::query()->max('id'); //get last inserted row id
$parent = App\Parent::find($lastId);
$child = $parent->children()->create([
'message' => 'A new comment.',
]);
您也可以使用createMany
方法
$parent = App\Parent::find($lastId);
$parent->children()->createMany([
[
'message' => 'A new comment.',
],
[
'message' => 'Another new comment.',
],
]);
通过在父 model 的关系上使用create
和createMany
来尝试使用此代码:
// Create the parent object.
$parent = Parent::create([
'name' => 'Parent 1'
]);
// Insert one.
$child = $parent->children()->create([
'name' => 'Child 1',
]);
// Insert many.
$parent->children()->createMany([
[
'name' => 'Child 2',
],
[
'name' => 'Child 3',
],
]);
你可以试试这个
try {
DB::beginTransaction();
$parent = Parent::create([
'name' => 'Parent name'
]);
$parent->children()->create([
'parent_id' => $parent->id,
'name' => 'Child name'
]);
DB::commit();
} catch (Exception $e) {
DB::rollback();
}
改变外键——在数据库上运行这个 sql
alter table child drop constraint child_parent_id;
alter table child add foreign key (parent_id) references parent(id) deferrable initially deferred;
这将允许您按任一顺序创建子级或父级,并且在提交之前不会验证约束。 在这种情况下应该没有必要 - 但是,它确实取决于您的 ID 是如何生成的。
儿童 function 需要一个中间表将其更改为:
public function children()
{
return $this->belongsToMany(Child::class);
}
不要这样做$parent->children()->save($child);
.
或者,如果您想 go 那样制作child_parent
表,其中包含 2 个字段child_id
和parent_id
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.