插入数据库时​​如何忽略嵌入式结构字段?

问题描述

我有2个数据库表; A有3列,分别是X,Y,Z B有2列,分别是X,W

我的Go结构是这样的

type Base struct {
    X int
    Y int
}

type A struct {
    Base
    Z int
}

type B struct {
    Base
    W int
}

然后我像这样初始化我的结构;

    a := A{Base: Base{X: 1,Y:2},Z: 3}
    b := B{Base: Base{X: 1},W: 4}

当我想使用gorm.io ORM将它们插入数据库时​​,插入“ a”没有问题,但是不能插入“ b”,因为postgresql给我类似的错误

pq: column "y" of relation "B" does not exist

如何在不创建另一个没有“ Y”字段的基本模型的情况下将“ b”插入数据库

解决方法

将结构分配给另一个结构并创建该结构的实例时,所有结构字段均已填充为它们的默认数据类型值。

例如:int的默认值为0。

因此您有2个解决方案。

  1. 创建两个不同的结构(不包含Base结构),仅创建AB。像这样:(也许您知道这个解决方案。)。
type A struct {
    X int
    Y int
    Z int
}

type B struct {
    X int
    W int
}
  1. 使用struct tags防止插入gorm

注意:我没有对此进行测试。

type Base struct {
    X int 
    Y int `json:"y,omitempty"`
}

type A struct {
    Base
    Z int
}

type B struct {
    Base
    W int
}
,

我认为您没有正确声明模型,因为文档“基础”应该在A和B两者中都嵌入标签,这样就可以了。 ..为了您更好的理解,我将发布经过修改的代码。请注意,我已经在我的机器上测试了它的魅力。

这是模型声明。

type Base struct {
    X int `json:"x"`
    Y int `json:"y"`
}

type A struct {
    Base `gorm:"embedded"`
    Z    int `json:"z"`
}

type B struct {
    Base `gorm:"embedded"`
    W    int `json:"w"`
}

这是您了解的主要功能。 。

func main() {
    fmt.Println("vim-go")
    db,err := gorm.Open("postgres","host=localhost port=5432 user=postgres 
dbname=testd password=postgres sslmode=disable")
    if err != nil {
        log.Panic("error occured",err)
    }
    db.AutoMigrate(&A{},&B{})

    a := &A{Base: Base{X: 1,Y: 2},Z: 3}
    b := &B{Base: Base{X: 1},W: 3}

    if err := db.Create(a).Error; err != nil {
        log.Println(err)
    }

    if err := db.Create(b).Error; err != nil {
        log.Println(err)
    }

    fmt.Println("everything is ok")
    defer db.Close()
 }

请确保检查模型声明和标签的文档。 。 。 gorm model declaration

注意:Y字段将出现在B表中,但值为零。 。

,
package main
import (
"encoding/json"
"fmt"
"reflect"
)
type SearchResult struct {
OrderNumber     string      `json:"orderNumber"`
Qunatity        interface{} `json:"qty"`
Price           string      `json:"price"`
OrderType       interface{} `json:"type"`
ItemQty         string      `json:"itemQty"`
}
type Or []SearchResult
func fieldSet(fields ...string) map[string]bool {
set := make(map[string]bool,len(fields))
for _,s := range fields {
    set[s] = true
}
return set
}
func (s *SearchResult) SelectFields(fields ...string) map[string]interface{} {
    fs := fieldSet(fields...)
    rt,rv := reflect.TypeOf(*s),reflect.ValueOf(*s)
    out := make(map[string]interface{},rt.NumField())
    for i := 0; i < rt.NumField(); i++ {
        field := rt.Field(i)
        jsonKey := field.Tag.Get("json")
        if fs[jsonKey] {
            out[jsonKey] = rv.Field(i).Interface()
    }
   }
    return out
 }
 func main() {
    result := &SearchResult{
    Date:     "to be honest you should probably use a time.Time field here,just sayin",Industry: "rocketships",IdCity:   "interface{} is kinda inspecific,but this is the idcity field",City:     "New York Fuckin' City",}
    b,err := json.MarshalIndent(result.SelectFields("orderNumber","qty"),"","  ")
   if err != nil {
        panic(err.Error())
    }
    var or Or
    fmt.Print(string(b))
or=append(or,*result)
or=append(or,*result)
for i := 0; i < len(or); i++ {
c,err := json.MarshalIndent(or[i].SelectFields("idCity","city","company"),"  ")
 if err != nil {
    panic(err.Error())
 }
 fmt.Print(string(c))
 }
 }

使用结构体中的省略字段和其他方式来做到这一点的一种方法是遍历结构体字段,这是昂贵的。 如果性能对你来说并不重要,那么你可以参考上面的代码片段。