90654


下記の構造体について、一つのLectureInfoに複数のTeacherが配属されているという形で保存したいです。

[code]

    type LectureInfo struct {
        gorm.Model
        Name     string
        Teachers []Teacher `gorm:"foreignKey:LectureID"`
    }
    type Teacher struct {
        gorm.Model
        LectureID string
        //以下略
    }
    
[/code]

最初にLectureInfoを登録して、後からTeacherを追加するという形をとっていますが、そのTeacherがうまくLectureInfo.Teachersに追加されません。  
まず、データベースの初期化が下記で

[code]

    func lidbInit() {
        db, err := gorm.Open("sqlite3", "lectureInfo.sqlite3")
        db.AutoMigrate(&LectureInfo{}, &Teacher{} /*, &EvaluationMethod{}, &RequiredKnowledge{}, &Comment{}*/)
        defer db.Close()
    }
    
[/code]

その次のLectureInfoの登録が下記で

[code]

    func lidbInsertLecture(lectureName string, teachers []Teacher) {
        db := gorm.Open("sqlite3", "lectureInfo.sqlite3")
        db.Create(&LectureInfo{Name: lectureName, Teachers: teachers})
        defer db.Close()
    }
    
[/code]

最後にteacherの追加がこれです

[code]

    //add teacher ID
    func lidbAddTeacher(lectureID string, teacher Teacher) {
        db:= gorm.Open("sqlite3", "lectureInfo.sqlite3")
        var lectureInfo LectureInfo
        db.First(&lectureInfo, lectureID)
        lectureInfo.Teachers = append(lectureInfo.Teachers, teacher)
        /////////////////
        fmt.Println(lectureInfo.Teachers)
         /////////////////
        db.Save(&lectureInfo)
        db.Close()
    }
    
[/code]

もし正しく追加できていれば、二回目のteacherの追加で2つのteacherがリストでコンソールに表示されるはずですが（///で囲った部分）、これでは二度目の追加では一つしか追加できていず、（Fuji,
Gokamiの順で登録したつもりが、[Fuji, Gokami]ではなく[Gokami]しか表示されなかった）になってしまっています。

また、下記のコードでLectureInfoを取得しようとしても、LectureInfo.Teachersが空スライスになっています

[code]

    func lidbGetOne(id int) LectureInfo {
        db := gorm.Open("sqlite3", "lectureInfo.sqlite3")
        var lectureInfo LectureInfo
        db.First(&lectureInfo, id)
        db.Close()
        return lectureInfo
    }
    
[/code]

おそらく私のSQLに対する理解不足に起因していますが、正しくteacherを追加するにはどうすればいいのかご教示いただけないでしょうか。


CC BY-SA 4.0
2022-07-29T08:43:34.647
90272
2022-08-20T16:54:48.840
2022-07-29T09:17:13.423
3060
53757
question
go gorm
構造体がスライスを持つときについて


### teachers に追加されていないように見える理由

一見 2 件目の teacher 追加がうまくいっていないように見えるのは、`db.First(&lectureInfo, id)` の部分で
teachers テーブルを preload していないためです。このため `db.First` した直後での `lectureInfo.Teachers`
が `[]` になっています。

代わりに、

[code]

    db.Preload("Teachers").First(&lectureInfo, id)
    
[/code]

と書くと Has Many で関連付けられている別テーブルのデータも一緒にクエリしてデータを持ってきてくれます。`lectureInfo.Teachers`
の値を確かめたり DB に対して DB クライアントから直接クエリしてレコードを列挙させたりして挙動を見てみてください。詳細:
<https://gorm.io/docs/preload.html>

### append の仕方

ところで、今回のように Has Many 関係にあるテーブルにレコードを追加するとき、GORM にはそれ専用の関数が用意されています:
<https://gorm.io/docs/associations.html#Append-Associations>

[code]

    db.Model(&lectureInfo).Association("Teachers").Append(&teacher)
    
[/code]

これを使うとわざわざ既存の teachers を読み込まなくても良いです。

* * *

本題とは関係ない指摘：今回 `Teachers` の `LectureID` は `string` 型になっていますが、`LectureInfo` の
`ID` は `uint` 型なので特に意図がなければ `uint` 型に揃えるのが自然です。


CC BY-SA 4.0
2022-08-20T16:54:48.840
90654
2022-08-20T16:54:48.840
19110
90272
answer