論理削除を実装するために、gorm.DeletedAtを使用した場合、レコードの取得のクエリが論理削除されたデータを取得しないように自動的に切り替わる。
場合によって、論理削除したレコードも取得したことがあるため、論理削除したレコードを取得する方法についても備忘録として残す。
gorm.DeletedAtカラムがある場合のオブジェクト取得のクエリ
以下は公式ドキュメントのサンプルを流用
https://gorm.io/ja_JP/docs/query.html
type User struct {
ID string `gorm:"primarykey;size:16"`
Name string `gorm:"size:24"`
DeletedAt gorm.DeletedAt `gorm:"index"` // Gormの特定のフィールドタイプの使用
}
var user = User{ID: 15}
db.First(&user) // 論理削除を実装している構造体でFirst()メソッドを実行
// SELECT * FROM `users` WHERE `users`.`id` = '15' AND `users`.`deleted_at` IS NULL ORDER BY `users`.`id` LIMIT 1
注目して欲しいのが、コメントアウトされている生成されるクエリである。
以下は見やすいように整形したもの。
SELECT *
FROM `users`
WHERE `users`.`id` = '15' AND
`users`.`deleted_at` IS NULL // このwhere句に注目
ORDER BY `users`.`id`
LIMIT 1
論理削除が含まれる構造体に対するクエリにはwhere句の中に「deleted_at IS NULL」の条件が含まれている。
つまり、デフォルトでdeleted_atカラムがNULL以外のレコードが条件となっている。
通常であれば、論理削除されたものは取得しなくてもよいため、Gormは親切なメソッドを作成してくれている。
論理削除されたレコードを取得する。「Unscoped()メソッド」
仕様や要件によっては論理削除したレコードも取得したことがある。
この論理削除されたレコードを取得する方法も公式に載っているため、紹介する。
https://gorm.io/ja_JP/docs/delete.html
db.Unscoped().Where("age = 20").Find(&users)
// SELECT * FROM users WHERE age = 20;
論理削除されたレコードは「Unscoped()メソッド」を使用することで取得することができる。
論理削除のレコードを取得しないデフォルトのクエリを打ち消すサンプルコード
type User struct {
ID string `gorm:"primarykey;size:16"`
Name string `gorm:"size:24"`
DeletedAt gorm.DeletedAt `gorm:"index"` // Gormの特定のフィールドタイプの使用
}
var user = User{ID: 15}
db.Unscoped().First(&user)
通常のgormを使用したコードの前にUnscoped()を追加するだけ。
まとめ
Gormでは論理削除の実装及びそれを考慮したレコードの取得が簡単に行える。
ただし、論理削除が含まれる構造体へのGormのデフォルトのクエリが変化するため、注意が必要。
論理削除されたレコードを取得したい場合は「Unscoped()メソッド」を使用すること。