Has One

A has one association sets up a one-to-one connection with another model, but with somewhat different semantics (and consequences). This association indicates that each instance of a model contains or possesses one instance of another model.

For example, if your application includes users and credit cards, and each user can only have one credit card.

Declare

  1. // User has one CreditCard, UserID is the foreign key
  2. type User struct {
  3. gorm.Model
  4. CreditCard CreditCard
  5. }
  6. type CreditCard struct {
  7. gorm.Model
  8. Number string
  9. UserID uint
  10. }

Retrieve

  1. // Retrieve user list with eager loading credit card
  2. func GetAll(db *gorm.DB) ([]User, error) {
  3. var users []User
  4. err := db.Model(&User{}).Preload("CreditCard").Find(&users).Error
  5. return users, err
  6. }

Override Foreign Key

For a has one relationship, a foreign key field must also exist, the owner will save the primary key of the model belongs to it into this field.

The field’s name is usually generated with has one model’s type plus its primary key, for the above example it is UserID.

When you give a credit card to the user, it will save the User’s ID into its UserID field.

If you want to use another field to save the relationship, you can change it with tag foreignKey, e.g:

  1. type User struct {
  2. gorm.Model
  3. CreditCard CreditCard `gorm:"foreignKey:UserName"`
  4. // use UserName as foreign key
  5. }
  6. type CreditCard struct {
  7. gorm.Model
  8. Number string
  9. UserName string
  10. }

Override References

By default, the owned entity will save the has one model’s primary key into a foreign key, you could change to save another field’s value, like using Name for the below example.

You are able to change it with tag references, e.g:

  1. type User struct {
  2. gorm.Model
  3. Name string `gorm:"index"`
  4. CreditCard CreditCard `gorm:"foreignKey:UserName;references:name"`
  5. }
  6. type CreditCard struct {
  7. gorm.Model
  8. Number string
  9. UserName string
  10. }

Polymorphism Association

GORM supports polymorphism association for has one and has many, it will save owned entity’s table name into polymorphic type’s field, primary key into the polymorphic field

  1. type Cat struct {
  2. ID int
  3. Name string
  4. Toy Toy `gorm:"polymorphic:Owner;"`
  5. }
  6. type Dog struct {
  7. ID int
  8. Name string
  9. Toy Toy `gorm:"polymorphic:Owner;"`
  10. }
  11. type Toy struct {
  12. ID int
  13. Name string
  14. OwnerID int
  15. OwnerType string
  16. }
  17. db.Create(&Dog{Name: "dog1", Toy: Toy{Name: "toy1"}})
  18. // INSERT INTO `dogs` (`name`) VALUES ("dog1")
  19. // INSERT INTO `toys` (`name`,`owner_id`,`owner_type`) VALUES ("toy1","1","dogs")

You can change the polymorphic type value with tag polymorphicValue, for example:

  1. type Dog struct {
  2. ID int
  3. Name string
  4. Toy Toy `gorm:"polymorphic:Owner;polymorphicValue:master"`
  5. }
  6. type Toy struct {
  7. ID int
  8. Name string
  9. OwnerID int
  10. OwnerType string
  11. }
  12. db.Create(&Dog{Name: "dog1", Toy: Toy{Name: "toy1"}})
  13. // INSERT INTO `dogs` (`name`) VALUES ("dog1")
  14. // INSERT INTO `toys` (`name`,`owner_id`,`owner_type`) VALUES ("toy1","1","master")

CRUD with Has One

Please checkout Association Mode for working with has one relations

Eager Loading

GORM allows eager loading has one associations with Preload or Joins, refer Preloading (Eager loading) for details

Self-Referential Has One

  1. type User struct {
  2. gorm.Model
  3. Name string
  4. ManagerID *uint
  5. Manager *User
  6. }

FOREIGN KEY Constraints

You can setup OnUpdate, OnDelete constraints with tag constraint, it will be created when migrating with GORM, for example:

  1. type User struct {
  2. gorm.Model
  3. CreditCard CreditCard `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
  4. }
  5. type CreditCard struct {
  6. gorm.Model
  7. Number string
  8. UserID uint
  9. }

You are also allowed to delete selected has one associations with Select when deleting, checkout Delete with Select for details