GORM中的复杂更新 [英] A complex update in GORM
问题描述
我在GORM中有一个模型,其中有Postgres作为数据库.模型是这样的
I have a model in GORM with Postgres as database. The model is like this
type Country struct {
gorm.Model
Name string
Population int64
Regions []Region
}
type Region struct {
gorm.Model
Name string
Cities []City
CountryID uint `sql:"type:bigint REFERENCES countries(id) ON DELETE CASCADE" json:"-"`
}
type City struct {
gorm.Model
Name string
Comment string
RegionID uint `sql:"type:bigint REFERENCES regions(id) ON DELETE CASCADE" json:"-"`
}
当我从模型创建新记录时,我调用create函数
When I create a new record from model, I invoke create function
db.Create(&menu)
现在,我正在尝试更新模型,但出现了一些问题.如果我调用此
Now, I'm trying to update the model and I have some issues. If I invoke this
err = db.Debug().Where("id = ?", countryId).Updates(&country).Error
我有一个错误,该模型未在数据库中更新更新:错误是
I have an error an the model is not updated in database UPDATED: The error is
(C:/source/go/gorm/country.go:100)
[2020-06-06 02:37:59] sql: converting argument $4 type: unsupported type []main.Region, a slice of struct
(C:/source/go/gorm/country.go:100)
[2020-06-06 02:37:59] [0.00ms] UPDATE "" SET "created_at" = '2020-06-06 00:37:50', "id" = 1, "name" = 'New Name', "regions" = '[{{1 2020-06-06 00:37:50.450497 +0000 UTC 2020-06-06 00:37:50.450497 +0000 UTC <nil>} Region 1 [{{1 2020-06-06 00:37:50.465029 +0000 UTC 2020-06-06 00:37:50.465029 +0000 UTC <nil>} City 1 1}] 1} {{0 0001-01-01 00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC <nil>} Region 2 updated [{{0 0001-01-01 00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC <nil>} City 2 updated 0}] 0}]', "updated_at" = '2020-06-06 00:37:50' WHERE (id = 1)
[0 rows affected or returned ]
如果我运行
err = db.Debug().Model(&country).Association("Regions").Replace(country.Regions).Error
在数据库中更新了地区和城市模型,但未更新国家/地区模型.除此之外,对于区域模型在更新过程中,delete元素的CountryID为null,但城市模型不会将其RegionID更新为取消引用.
The regions and cities models are updated in database but country model is not updated. Added to this, for regions model during update delete elements has null for CountryID but cities model doesn't update its RegionID to dereference.
如何更新这样的完整模型?
How can I update a complete model like this?
更新:
我不知道如何更新完整的国家/地区模型.这是执行的完整查询.
I don't know how to update a complete Country model. This is the full queries executed.
Create Tables
(C:/source/go/gorm/country.go:35)
[2020-06-06 01:33:29] [36;1m[20.02ms] CREATE TABLE "countries" ("id" serial,"created_at" timestamp with time zone,"updated_at" timestamp with time zone,"deleted_at" timestamp with time zone,"name" text,"population" bigint , PRIMARY KEY ("id"))
[36;31m[0 rows affected or returned ]
(C:/source/go/gorm/country.go:35)
[2020-06-06 01:33:29] [36;1m[16.00ms] CREATE INDEX idx_countries_deleted_at ON "countries"(deleted_at)
[36;31m[0 rows affected or returned ]
(C:/source/go/gorm/country.go:36)
[2020-06-06 01:33:29] [36;1m[28.99ms] CREATE TABLE "regions" ("id" serial,"created_at" timestamp with time zone,"updated_at" timestamp with time zone,"deleted_at" timestamp with time zone,"name" text,"country_id" bigint REFERENCES countries(id) ON DELETE CASCADE , PRIMARY KEY ("id"))
[36;31m[0 rows affected or returned ]
(C:/source/go/gorm/country.go:36)
[2020-06-06 01:33:29] [36;1m[11.99ms] CREATE INDEX idx_regions_deleted_at ON "regions"(deleted_at)
[36;31m[0 rows affected or returned ]
(C:/source/go/gorm/country.go:37)
[2020-06-06 01:33:29] [36;1m[18.99ms] CREATE TABLE "cities" ("id" serial,"created_at" timestamp with time zone,"updated_at" timestamp with time zone,"deleted_at" timestamp with time zone,"name" text,"comment" text,"region_id" bigint REFERENCES regions(id) ON DELETE CASCADE , PRIMARY KEY ("id"))
[36;31m[0 rows affected or returned ]
(C:/source/go/gorm/country.go:37)
[2020-06-06 01:33:29] [36;1m[32.00ms] CREATE INDEX idx_cities_deleted_at ON "cities"(deleted_at)
[36;31m[0 rows affected or returned ]
Add Country Model
(C:/source/go/gorm/country.go:64)
[2020-06-06 01:33:32] [36;1m[3.99ms] INSERT INTO "countries" ("created_at","updated_at","deleted_at","name","population") VALUES ('2020-06-06 01:33:32','2020-06-06 01:33:32',NULL,'Country 1',0) RETURNING "countries"."id"
[36;31m[1 rows affected or returned ]
(C:/source/go/gorm/country.go:64)
[2020-06-06 01:33:32] [36;1m[4.00ms] INSERT INTO "regions" ("created_at","updated_at","deleted_at","name","country_id") VALUES ('2020-06-06 01:33:32','2020-06-06 01:33:32',NULL,'Region 1',1) RETURNING "regions"."id"
[36;31m[1 rows affected or returned ]
(C:/source/go/gorm/country.go:64)
[2020-06-06 01:33:32] [36;1m[3.00ms] INSERT INTO "cities" ("created_at","updated_at","deleted_at","name","comment","region_id") VALUES ('2020-06-06 01:33:32','2020-06-06 01:33:32',NULL,'City 1','',1) RETURNING "cities"."id"
[36;31m[1 rows affected or returned ]
(C:/source/go/gorm/country.go:64)
[2020-06-06 01:33:32] [36;1m[4.00ms] INSERT INTO "regions" ("created_at","updated_at","deleted_at","name","country_id") VALUES ('2020-06-06 01:33:32','2020-06-06 01:33:32',NULL,'Region 2',1) RETURNING "regions"."id"
[36;31m[1 rows affected or returned ]
(C:/source/go/gorm/country.go:64)
[2020-06-06 01:33:32] [36;1m[3.83ms] INSERT INTO "cities" ("created_at","updated_at","deleted_at","name","comment","region_id") VALUES ('2020-06-06 01:33:32','2020-06-06 01:33:32',NULL,'City 2','',2) RETURNING "cities"."id"
[36;31m[1 rows affected or returned ]
Update Country Model
(C:/source/go/gorm/country.go:75)
[2020-06-06 01:33:39] [36;1m[3.99ms] SELECT * FROM "countries" WHERE "countries"."deleted_at" IS NULL AND ((id = 1))
[36;31m[1 rows affected or returned ]
(C:/source/go/gorm/country.go:75)
[2020-06-06 01:33:39] [36;1m[4.00ms] SELECT * FROM "regions" WHERE "regions"."deleted_at" IS NULL AND (("country_id" IN (1)))
[36;31m[2 rows affected or returned ]
(C:/source/go/gorm/country.go:75)
[2020-06-06 01:33:39] [36;1m[3.00ms] SELECT * FROM "cities" WHERE "cities"."deleted_at" IS NULL AND (("region_id" IN (1,2)))
[36;31m[2 rows affected or returned ]
{{1 2020-06-05 23:33:32.660156 +0000 UTC 2020-06-05 23:33:32.660156 +0000 UTC <nil>} Country 1 0 [{{1 2020-06-05 23:33:32.664151 +0000 UTC 2020-06-05 23:33:32.664151 +0000 UTC <nil>} Region 1 [{{1 2020-06-05 23:33:32.668156 +0000 UTC 2020-06-05 23:33:32.668156 +0000 UTC <nil>} City 1 1}] 1} {{2 2020-06-05 23:33:32.672155 +0000 UTC 2020-06-05 23:33:32.672155 +0000 UTC <nil>} Region 2 [{{2 2020-06-05 23:33:32.676156 +0000 UTC 2020-06-05 23:33:32.676156 +0000 UTC <nil>} City 2 2}] 1}]}
(C:/source/go/gorm/country.go:99)
[2020-06-06 01:33:39] [36;1m[3.00ms] UPDATE "regions" SET "created_at" = '2020-06-05 23:33:32', "updated_at" = '2020-06-06 01:33:39', "deleted_at" = NULL, "name" = 'Region 1', "country_id" = 1 WHERE "regions"."deleted_at" IS NULL AND "regions"."id" = 1
[36;31m[1 rows affected or returned ]
()
[2020-06-06 01:33:39] [36;1m[6.00ms] UPDATE "cities" SET "created_at" = '2020-06-05 23:33:32', "updated_at" = '2020-06-06 01:33:39', "deleted_at" = NULL, "name" = 'City 1', "comment" = '', "region_id" = 1 WHERE "cities"."deleted_at" IS NULL AND "cities"."id" = 1
[36;31m[1 rows affected or returned ]
(C:/source/go/gorm/country.go:99)
[2020-06-06 01:33:39] [36;1m[4.00ms] SELECT * FROM "countries" WHERE "countries"."deleted_at" IS NULL AND "countries"."id" = 1 ORDER BY "countries"."id" ASC LIMIT 1
[36;31m[1 rows affected or returned ]
(C:/source/go/gorm/country.go:99)
[2020-06-06 01:33:39] [36;1m[3.00ms] UPDATE "regions" SET "created_at" = '2020-06-05 23:33:32', "updated_at" = '2020-06-06 01:33:39', "deleted_at" = NULL, "name" = 'Region 1', "country_id" = 1 WHERE "regions"."deleted_at" IS NULL AND "regions"."id" = 1
[36;31m[1 rows affected or returned ]
()
[2020-06-06 01:33:39] [36;1m[4.99ms] UPDATE "cities" SET "created_at" = '2020-06-05 23:33:32', "updated_at" = '2020-06-06 01:33:39', "deleted_at" = NULL, "name" = 'City 1', "comment" = '', "region_id" = 1 WHERE "cities"."deleted_at" IS NULL AND "cities"."id" = 1
[36;31m[1 rows affected or returned ]
(C:/source/go/gorm/country.go:99)
[2020-06-06 01:33:39] [36;1m[4.00ms] INSERT INTO "regions" ("created_at","updated_at","deleted_at","name","country_id") VALUES ('2020-06-06 01:33:39','2020-06-06 01:33:39',NULL,'Region 2 updated',1) RETURNING "regions"."id"
[36;31m[1 rows affected or returned ]
()
[2020-06-06 01:33:39] [36;1m[3.99ms] INSERT INTO "cities" ("created_at","updated_at","deleted_at","name","comment","region_id") VALUES ('2020-06-06 01:33:39','2020-06-06 01:33:39',NULL,'City 2 updated','',3) RETURNING "cities"."id"
[36;31m[1 rows affected or returned ]
(C:/source/go/gorm/country.go:99)
[2020-06-06 01:33:39] [36;1m[3.00ms] SELECT * FROM "countries" WHERE "countries"."deleted_at" IS NULL AND "countries"."id" = 1 ORDER BY "countries"."id" ASC LIMIT 1
[36;31m[1 rows affected or returned ]
(C:/source/go/gorm/country.go:99)
[2020-06-06 01:33:39] [36;1m[3.99ms] UPDATE "regions" SET "country_id" = NULL WHERE "regions"."deleted_at" IS NULL AND (("id" NOT IN (1,3)) AND ("country_id" = 1))
[36;31m[1 rows affected or returned ]
推荐答案
要更新现有数据,您可以获取第一个预加载子对象
For update existing data you can fetch first preloading child
var country Country
db.Preload("Regions").Preload("Regions.Cities").First(&country, 1)
然后您可以更新数据并添加新数据,例如
Then you can update the data and add new data like
country.Regions[0].Cities[0].Name = "Dhaka City 1"
country.Regions[0].Name = "Dhaka Region 1"
country.Regions[1].Cities = append(country.Regions[1].Cities, City{Name: "Dhaka City 2"})
现在将更新的数据保存在数据库中
Now save the updated data in database
db.Save(&country)
如果只想添加新的子数据,则也可以避免预加载.
If you want to add new child data only you can avoid Preload also.
db.First(&country, 8)
country.Regions = append(country.Regions, Region{Name: "Dhaka Region 3"})
db.Save(&country)
默认情况下,gorm association_autoupdate
标志设置为 true
,因此它是自动保存关联.
By default gorm association_autoupdate
flag set as true
, so it's auto save association.
err = db.Debug().Model(&country).Association("Regions").Replace(country.Regions).Error
仅将关联方式替换为其他.如果您不提供任何内容,则会在此处删除与 Country
的当前关联.而且只有 Regions
(不是地区)/是子城市.
Replace only replace the association means with other. If you don't give any it will just remove current association with Country
here. And only Regions
not it's child city.
Gorm在更新时不支持任何删除操作.它仅用于添加或更新现有数据.Gorm模型默认使用软删除.如果以这种方式删除区域,它将更新 deleted_at
字段数据.而且在查询时,它始终会过滤出已删除的数据.
Gorm doesn't support any delete operation on update. It just use for add or update existing data.
Gorm model uses soft delete by default. If you delete Regions this way, it will update the deleted_at
field data. And when query it always filter out deleted data.
db.Delete(county.Regions)
它不会软删除城市,您必须这样做.
And it won't soft delete City, you have to do this way.
db.Delete(region.Cities)
一个有效的代码示例此处
这篇关于GORM中的复杂更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!