7
                            go1.15
gf master
orm中的ScanList功能,在复杂情况下会失效
示例代码:
// 多个用户,每个用户有多本书,每本书有一个出版社信息
//出版社
type PublishingHouse struct {
    Id int `json:"id"`
}
type Book struct {
    Id              int             `json:"id"`
    Name            string          `json:"name"`
    UserId          int             `json:"user_id"`
    CreateAt        *gtime.Time     `json:"created_at"`
    PublishingHouse PublishingHouse `json:"publishing_house"` //如果去掉这一属性能赋值成功,但实际在多层嵌套时,中间一些层,基本上都会是这样的形式
}
type User struct {
    Id       int         `json:"id"`
    Nickname string      `json:"nickname"`
    CreateAt *gtime.Time `json:"created_at"`
}
type UserEntity struct {
    User
    Books []Book `json:"books"`
}
func createTableUser() string {
    db := g.Database()
    db.SetDebug(true)
    tableName := "users_" + gconv.String(gtime.Now().Nanosecond())
    if _, err := db.Exec(fmt.Sprintf(`
        CREATE TABLE %s (
            id          int(10) unsigned NOT NULL AUTO_INCREMENT,
            nickname    varchar(45) NULL,
            created_at    datetime NULL,
            PRIMARY KEY (id)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
        `, tableName,
    )); err != nil {
        gtest.Fatal(err)
    }
    return tableName
}
func createTableBook() string {
    db := g.Database()
    db.SetDebug(true)
    tableName := "books_" + gconv.String(gtime.Now().Nanosecond())
    if _, err := db.Exec(fmt.Sprintf(`
        CREATE TABLE %s (
            id          int(10) unsigned NOT NULL AUTO_INCREMENT,
            name    varchar(45) NULL,
            user_id    int(10) NULL,
            created_at    datetime NULL,
            PRIMARY KEY (id)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
        `, tableName,
    )); err != nil {
        gtest.Fatal(err)
    }
    return tableName
}
func fillData(tableName1 string, tableName2 string) {
    db := g.Database()
    for i := 0; i < 5; i++ {
        user := &User{
            Nickname: "张" + gconv.String(i),
        }
        if rs, err := db.Table(tableName1).Save(user); err == nil {
            rsLid, _ := rs.LastInsertId()
            for j := 0; j < 3; j++ {
                book := &Book{
                    Name:   "书" + gconv.String(j),
                    UserId: gconv.Int(rsLid),
                }
                db.Table(tableName2).Save(book)
            }
        }
    }
}
// 删除表
func dropTable(table []string) {
    db := g.Database()
    for _, v := range table {
        if _, err := db.Exec(fmt.Sprintf("DROP TABLE IF EXISTS `%s`", v)); err != nil {
            gtest.Error(err)
        }
    }
}
func TestScanList(t *testing.T) {
    userName := createTableUser()
    bookName := createTableBook()
    fillData(userName, bookName)
    db := g.Database()
    var entity []UserEntity
    _ = db.Table(userName).Structs(&entity)
    _ = db.Table(bookName).Where("user_id", gdb.ListItemValuesUnique(&entity, "Id")).
        ScanList(&entity, "Books", "User", "user_id:Id")
    dropTable([]string{userName, bookName})
    for _, v := range entity {
        if v.Books == nil {
            g.Dump("err!")
        } else {
            g.Dump("ok!")
        }
    }
    g.Dump("done!")
}