gorm 预加载不适用于对象集合吗?

我需要从 db where 获取所有模块status != Complete

我的模块表与节表具有多对多映射,节表与字段表具有多对多映射。

我正在尝试使用下面的语句获取单个 DB 查询中的所有模块。

dbConnection.Set("gorm:auto_preload", true).Where("status != ?", enum.Completed).Find(&modules)

但它不返回部分和字段。如果我使用下面的语句,那么它会返回嵌套模型。

dbConnection.Set("gorm:auto_preload", true).Where("status != ?", enum.Completed).First(&modules)

这是否意味着它仅适用于单个记录而不适用于集合?


慕妹3242003
浏览 146回答 2
2回答

HUWWW

使用dbConnection.Set("gorm:auto_preload", true),您只能加载子关系,但如果您还想加载子的子关系,则必须使用嵌套预加载。像db.Preload("Sections").Preload("Sections.Fields").Find(&modules)

守着星空守着你

我根据你的描述写了一个示例代码,你可以在底部找到完整的代码。让我们来看看不同的选择:// Use auto_preload and .Firstdb.Set("gorm:auto_preload", true).Where("name = ?", "m0").First(&modules)Output:[{ID:1 Name:m0 Status:0 Sections:[{ID:2 Name:s1 Fields:[]}]}]因此,.First您可以得到部分,但不能得到Sections.Fields// Use auto_preload and .Finddb.Set("gorm:auto_preload", true).Find(&modules)Output:[{ID:1 Name:m0 Status:0 Sections:[{ID:2 Name:s1 Fields:[]}]} {ID:2 Name:m1 Status:0 Sections:[{ID:1 Name:s0 Fields:[]}]}]与.Find您获得相同的行为.First// Use .Preloaddb.Preload("Sections").Preload("Sections.Fields").Find(&modules)Output:[{ID:1 Name:m0 Status:0 Sections:[{ID:2 Name:s1 Fields:[{ID:1 Name:f0} {ID:2 Name:f1}]}]} {ID:2 Name:m1 Status:0 Sections:[{ID:1 Name:s0 Fields:[{ID:1 Name:f0} {ID:3 Name:f2}]}]}]通过显式预加载,您可以同时加载Sections和Sections.Fields。仅使用auto_preload预加载直接字段,而不是更深的字段。IMO 使用显式预加载通常是一种更好的做法。完整代码:package mainimport (    "fmt"    "github.com/jinzhu/gorm"    _ "github.com/jinzhu/gorm/dialects/sqlite"    "log")type Module struct {    ID       int `gorm:"primary_key"`    Name     string    Status   int    Sections []Section `gorm:"many2many:module_sections;"`}type Section struct {    ID     int `gorm:"primary_key"`    Name   string    Fields []Field `gorm:"many2many:section_fields;"`}type Field struct {    ID   int `gorm:"primary_key"`    Name string}func preloadingSample() error {    db, err := gorm.Open("sqlite3", "test.db")    if err != nil {        return fmt.Errorf("open DB failed: %w", err)    }    defer db.Close()    err = db.AutoMigrate(        &Module{},        &Section{},        &Field{},    ).Error    if err != nil {        return fmt.Errorf("migration failed: %w", err)    }    // Delete everything in DB    db.Delete(&Module{})    db.Delete(&Section{})    db.Delete(&Field{})    // Put some sample data in DB    sampleFields := []Field{        {Name: "f0"},        {Name: "f1"},        {Name: "f2"},        {Name: "f3"},    }    for idx := range sampleFields {        err = db.Create(&sampleFields[idx]).Error        if err != nil {            return fmt.Errorf("failed to create: %w", err)        }    }    sampleSections := []Section{        {Name: "s0", Fields: []Field{sampleFields[0], sampleFields[2]}},        {Name: "s1", Fields: []Field{sampleFields[0], sampleFields[1]}},    }    for idx := range sampleSections {        err = db.Create(&sampleSections[idx]).Error        if err != nil {            return fmt.Errorf("failed to create: %w", err)        }    }    sampleModules := []Module{        {Name: "m0", Sections: []Section{sampleSections[1]}},        {Name: "m1", Sections: []Section{sampleSections[0]}},    }    for idx := range sampleModules {        err = db.Create(&sampleModules[idx]).Error        if err != nil {            return fmt.Errorf("failed to create: %w", err)        }    }    var modules []Module    // Load just one module with auto_preload    err = db.Set("gorm:auto_preload", true).Where("name = ?", "m0").First(&modules).Error    if err != nil {        return fmt.Errorf("auto_preload first: %w", err)    }    fmt.Printf("%+v\n", modules)    // Load all modules with auto_preload    err = db.Set("gorm:auto_preload", true).Find(&modules).Error    if err != nil {        return fmt.Errorf("auto_preload find: %w", err)    }    fmt.Printf("%+v\n", modules)    // Explicitly load    err = db.Preload("Sections").Preload("Sections.Fields").Find(&modules).Error    if err != nil {        return fmt.Errorf("preload find: %w", err)    }    fmt.Printf("%+v\n", modules)    return nil}func main() {    err := preloadingSample()    if err != nil {        log.Fatal(err)    }}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go