Gormで外部キーを設定する

GOでwebアプリケーションを作ることになり、ORマッパーにgormを採用したのですが、外部キーの設定についてメモ。

Gormを利用して外部キーを設定する

外部キーを設定するにあったって下記の手順を行いました。

1. Structでデータを定義する

UserがCreditCardをHasOneで持っているAssociationを定義します。 CreditCardのUserIDがFKになる予定です。

type User struct {
  gorm.Model
  Name string	
}

type CreditCard struct {
  gorm.Model
  User 	  User
  UserID 	int
  Number  string
}

この状態で、Migrateをしてみます。

db.AutoMigrate(&User{}, &CreditCard{})

実際にテーブルのindexがどうなったか確認すると。

SELECT 
  TABLE_NAME, 
  COLUMN_NAME, 
  CONSTRAINT_NAME, 
  REFERENCED_TABLE_NAME, 
  REFERENCED_COLUMN_NAME  
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE 
WHERE TABLE_NAME = 'credit_cards'
Empty set (0.00 sec)

テーブルには外部キーが貼られてないようです。

2. AddForeignKeyを利用する

こちらのissueを見つけました。 実際にFKを貼るのであれば、AddForeignKey関数を利用すればいいとのこと。

AddForeignKeyは下記のような引数を取ります。

func (s *DB) AddForeignKey(field string, dest string, onDelete string, onUpdate string) *DB {
  ・・・
}

上記を参考に、先程のmigrate処理を変更します。

db.AutoMigrate(&User{})
db.AutoMigrate(&CreditCard{}).AddForeignKey("user_id", "users(id)", "RESTRICT", "RESTRICT")`

3. Error 1215の場合はdata型が一致していないので調整する

今回の場合、credit_cardsのuser_idの型指定をunsigned intにしていなかったので、参照カラムとのデータ型違いによりError 1215で外部キーを設定できませんでした。 定義を見直し、下記のように変更して調整しました。

(int > uintに変更するだけで問題ないかもしれません)

type CreditCard struct {
  gorm.Model
  User 	  User
  UserID 	int   `gorm:"type:INT(10) UNSIGNED; not null"`
  Number  string
}

再度マイグレーションを実行して確認すると、 問題なく貼れました!

+--------------+-------------+---------------------------------------+-----------------------+------------------------+ 
| TABLE_NAME   | COLUMN_NAME | CONSTRAINT_NAME                       | REFERENCED_TABLE_NAME | REFERENCED_COLUMN_NAME | 
+--------------+-------------+---------------------------------------+-----------------------+------------------------+ 
| credit_cards | id          | PRIMARY                               | NULL                  | NULL                   | 
| credit_cards | user_id     | credit_cards_user_id_users_id_foreign | users                 | id                     | 
+--------------+-------------+---------------------------------------+-----------------------+------------------------+

参考