Conventions

ID as Primary Key

GORMはデフォルトで、テーブルの主キーとして ID という名前のフィールドを使用します。

type User struct {
  ID   string //フィールドはデフォルトでは `ID` という名前のフィールドがプライマリフィールドとして使われます。
  Name string
}

他のフィールドを primaryKey タグで主キーとして設定できます

// Set field `UUID` as primary field
type Animal struct {
  ID     int64
  UUID   string `gorm:"primaryKey"`
  Name   string
  Age    int64
}

Composite Primary Key も参照してください。

Pluralized Table Name

GORMは構造体名をテーブル名としてsnake_casesのように複数形にします。構造体 User の場合、対応するテーブル名は規約により users となります。

TableName

Tabler インターフェイスを実装することで、デフォルトのテーブル名を変更することができます。例:

type Tabler interface {
TableName() string
}

// TableName overrides the table name used by User to `profiles`
func (User) TableName() string {
  return "profiles"
}

NOTE TableName doesn’t allow dynamic name, its result will be cached for future, to use dynamic name, you can use Scopes, for example:

func UserTable(user User) func (db *gorm.DB) *gorm.DB {
return func (db *gorm.DB) *gorm.DB {
if user.Admin {
return db.Table("admin_users")
}

return db.Table("users")
}
}

DB.Scopes(UserTable(user)).Create(&user)

Temporarily specify a name

Temporarily specify table name with Table method, for example:

// Create table `deleted_users` with struct User's fields
db.Table("deleted_users").AutoMigrate(&User{})

// Query data from another table
var deletedUsers []User
db.Table("deleted_users").Find(&deletedUsers)
// SELECT * FROM deleted_users;

db.Table("deleted_users").Where("name = ?", "jinzhu").Delete(&User{})
// DELETE FROM deleted_users WHERE name = 'jinzhu';

Check out From SubQuery for how to use SubQuery in FROM clause

NamingStrategy

GORM allows users change the default naming conventions by overriding the default NamingStrategy, which is used to build TableName, ColumnName, JoinTableName, RelationshipFKName, CheckerName, IndexName, Check out GORM Config for details

Column Name

Column db name uses the field’s name’s snake_case by convention.

type User struct {
  ID        uint      // column name is `id`
  Name      string    // column name is `name`
  Birthday  time.Time // column name is `birthday`
  CreatedAt time.Time // column name is `created_at`
}

You can override the column name with tag column or use NamingStrategy

type Animal struct {
  AnimalID int64     `gorm:"column:beast_id"`         // set name to `beast_id`
  Birthday time.Time `gorm:"column:day_of_the_beast"` // set name to `day_of_the_beast`
  Age      int64     `gorm:"column:age_of_the_beast"` // set name to `age_of_the_beast`
}

Timestamp Tracking

CreatedAt

For models having CreatedAt field, the field will be set to the current time when the record is first created if its value is zero

db.Create(&user) // set `CreatedAt` to current time

user2 := User{Name: "jinzhu", CreatedAt: time.Now()}
db.Create(&user2) // user2's `CreatedAt` won't be changed

// To change its value, you could use `Update`
db.Model(&user).Update("CreatedAt", time.Now())

UpdatedAt

For models having UpdatedAt field, the field will be set to the current time when the record is updated or created if its value is zero

db.Save(&user) // set `UpdatedAt` to current time

db.Model(&user).Update("name", "jinzhu") // will set `UpdatedAt` to current time

db.Model(&user).UpdateColumn("name", "jinzhu") // `UpdatedAt` won't be changed

user2 := User{Name: "jinzhu", UpdatedAt: time.Now()}
db.Create(&user2) // user2's `UpdatedAt` won't be changed when creating

user3 := User{Name: "jinzhu", UpdatedAt: time.Now()}
db.Save(&user3) // user3's `UpdatedAt` will change to current time when updating

NOTE GORM supports having multiple time tracking fields and track with UNIX (nano/milli) seconds, checkout Models for more details