💡

【GORM】V1からV2へアップグレードtips集

3 min read

はじめに

GORM V1からV2にアップグレードを行った際に、インターネット検索で出てこなかったところをtips集として書いてみます!

tips

PrimaryKeyの指定方法を変更

// V1
`gorm:"primary_key" json:"id"`

// V2
`gorm:"primaryKey" json:"id"`

jointable_foreignkey, association_jointable_foreignkeyの指定方法を変更

// V1
`gorm:"jointable_foreignkey:hoge;association_jointable_foreignkey:huga;" json:"ids"`

// V2
`gorm:"joinForeignKey:hoge;joinReferences:huga;" json:"ids"`

foreignkey, association_foreignkeyの指定方法を変更

// V1
`gorm:"foreignkey:hoge;association_foreignkey:huga;" json:"id"`

// V2
`gorm:"foreignKey:hoge;references:huga;" json:"id"`

詳細はこちらを確認してください。

https://gorm.io/docs/many_to_many.html#Override-Foreign-Key

V2でRecordNotFound()判定

エラーハンドリング方法が変わっているため、自前で共通関数を作成し、errorオブジェクトを渡して判定するようにしました。

import (
	"errors"

	"gorm.io/gorm"
)

func RecordNotFound(err error) bool {
	return errors.Is(err, gorm.ErrRecordNotFound)
}

https://gorm.io/docs/error_handling.html#ErrRecordNotFound
  • First, Findのエラーハンドリング

RecordNotFound()メソッドがV2から廃止になったことで、エラーハンドリングを自前で実装する場合の注意点

// V2
var db *gorm.DB
user := &orm.User{}
...
err := db.Where("uuid = ?", library.UUID()).First(user).Error
pretty.Println(err)
pretty.Println(errors.Is(err, gorm.ErrRecordNotFound))

> &errors.errorString{s:"record not found"}
> bool(true)

user := &orm.User{}
err := db.Where("uuid = ?", library.UUID()).Find(user).Error
pretty.Println(err)
pretty.Println(errors.Is(err, gorm.ErrRecordNotFound))

> nil
> bool(false)

.Find().Errorとした場合、gorm.ErrRecordNotFoundにならないので注意してください。
.First().Errorにメソッドを変更するか、nilならNotFoundにするようにしましょう。

テーブル名取得

// V1
var db *gorm.DB
var st orm.Users
...  
pretty.Println(db.NewScope(st).TableName())

> users

// V2
var db *gorm.DB
var st orm.Users
...
stmt := &gorm.Statement{DB: db}
stmt.Model = st
stmt.Parse(stmt.Model)
pretty.Println(stmt.Table)

> users

V2でテーブル名を取得する処理は、Execute()時点で何かしらしていると踏んでGORM V2のコードを読んで書きました。

カラムチェック

// V1
var db *gorm.DB
var st orm.Users
...  
pretty.Println(db.NewScope(st).HasColumn("Hoge"))

// orm.UsersにHogeカラムがあればtrue
> bool(true)

// V2
var db *gorm.DB
var st orm.Users
...  
pretty.Println(db.Migrator().HasColumn(st, "Hoge"))

> bool(true)

QueryExpr(未検証)

// V1
var db *gorm.DB
var st orm.Users
...  
pretty.Println(db.Table("sample").Where("id = 1").QueryExpr())

> &gorm.SqlExpr{
    expr: "SELECT * FROM `sample`  WHERE (id = 1)",
    args: nil,
}

// V2
var db *gorm.DB
var st orm.Users
...  
pretty.Println(db.Table("sample").Where("id = 1"))

> V1の処理はサブクエリだと思っているのでコレで大丈夫なはず…(未確認です)

おわりに

GORM V1からV2のアップグレードはかなり時間を要すると思いますので、事前にAPIの網羅テストがある状態でアップグレードするのが良いと思います。
少しでも誰かの助けになれば幸いです。

Discussion

ログインするとコメントできます