go - 使用 GORM 将接口设置为具有许多实现的属性
问题描述
我有一个 Postgres 数据库,它将 JSON 存储为其字段之一。表的结构是:
type Table struct {
ID int
VehicleType string
Vehicle Vehicle `gorm:"type:jsonb"`
// ......
}
现在,Vehicle 是一个接口
type Vehicle interface {
GetEngineModel() string
}
它有很多实现,我将分享其中一个——汽车
type Car struct {
CarEngineModel string //the attributes will be different for different
//implementation
}
func (car Car) GetEngineModel() string {
return car.CarEngineModel
}
为了解析特定结构中的属性,即 Car、Bike、..,我可以实现所有实现的 Scan 和 Value 接口,如下所示:-
func (car *Car) Scan(value interface{}) error {
//Want to use this implementation of Scan based on VehicleType
//attribute of struct table
b, ok := value.([]byte)
if !ok {
return errors.New("type assertion to []byte failed")
}
*car = json.Unmarshal(b, &car)
}
有没有办法根据其他表列来判断要使用哪个 Scan 实现,或者使用 GORM 来做同样的事情?我只想要一个表(遗传 json 类型),所以不想使用多态关联为不同的实现使用不同的表。
解决方案
您可以添加一个单独的字段来保存原始 JSON 数据,然后实现gorm
特定的挂钩来编组/解组该数据。
type Table struct {
ID int
VehicleType string
Vehicle Vehicle `gorm:"-"`
// ...
VehicleRaw []byte `gorm:"column:vehicle"`
}
func (t *Table) BeforeSave(tx *gorm.DB) (err error) {
raw, err := json.Marshal(t.Vehicle)
if err != nil {
return err
}
t.VehicleRaw = raw
return nil
}
func (t *Table) AfterFind(tx *gorm.DB) (err error) {
switch t.VehicleType {
case "CAR":
t.Vehicle = &Car{}
case "BIKE":
t.Vehicle = &Bike{}
}
return json.Unmarshal(t.VehicleRaw, t.Vehicle)
}
推荐阅读
- flask - 从使用 Flask 应用程序的 Microsoft PowerBI Embedded,我如何使用 url 过滤?
- ios - 观察者没有调用 swift iOS firebase 实时数据库
- firebase - Service Account does not have storage.objects.get access to the Google Cloud Storage object
- python - Python 最小 Modbus CRC 字节顺序
- html - 增加表中每 2 行之间的间隙
- typescript - 如何从键中派生 Typescript 类型的值
- python - 如何使用 gcloud 将 IP 从一个实例切换到另一个实例
- python - KivyMD AttributeError:“Data_base”对象没有属性“菜单”
- python - python中的子进程不允许读取
- selenium - java.lang.AbstractMethodError:io.cucumber.testng.TestNGCucumberOptionsProvider$TestNGCucumberOptions.publish()Z