GORM中的复杂更新 [英] A complex update in GORM

查看:39
本文介绍了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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆