无法与gorm创建外键关系,其中字段名称!=类型名称

I'm trying to create a "belongs-to" relationship in my application where the name of the field (and db column) is not the same as the type name. Gorm is complaining about this. Here is a short example that demonstrates the problem:

package main

import (
    "fmt"
    "github.com/jinzhu/gorm"
    _ "github.com/mattn/go-sqlite3"
)

type Car struct {
    gorm.Model
    Owner   User
    OwnerID int
}

type User struct {
    gorm.Model
}

func main() {
    db, _ := gorm.Open("sqlite3", "test.db")
    defer db.Close()
    db.LogMode(true)

    db.CreateTable(&Car{}, &User{})

    u := User{}
    u.ID = 1
    db.Create(&u)

    c := Car{}
    c.ID = 1
    c.Owner = u
    db.Create(&c)

    cars := make([]Car, 5)
    db.Find(&cars)
    for i := range cars {
        db.Model(cars[i]).Related(&cars[i].Owner)
    }

    for i := range cars {
        fmt.Println(cars[i].Owner.ID)
    }
}

We would expect this program to print out "1" as its last line, as this is the primary key of the Users relation that "owns" the only car in the database. Instead "0" is printed out, and verbose logging shows an error at the Related(&cars[i].Owner) step:

(/home/nate/gocode/src/foo/main.go:26)
[2016-04-09 19:33:46]  [122.35ms]  CREATE TABLE "cars" ("id" integer primary key autoincrement,"created_at" datetime,"updated_at" datetime,"deleted_at" datetime,"owner_id" integer )

(/home/nate/gocode/src/foo/main.go:26)
[2016-04-09 19:33:46]  [98.96ms]  CREATE INDEX idx_cars_deleted_at ON "cars"(deleted_at)

(/home/nate/gocode/src/foo/main.go:26)
[2016-04-09 19:33:46]  [108.95ms]  CREATE TABLE "users" ("id" integer primary key autoincrement,"created_at" datetime,"updated_at" datetime,"deleted_at" datetime )

(/home/nate/gocode/src/foo/main.go:26)
[2016-04-09 19:33:46]  [125.74ms]  CREATE INDEX idx_users_deleted_at ON "users"(deleted_at)

(/home/nate/gocode/src/foo/main.go:30)
[2016-04-09 19:33:46]  [0.53ms]  INSERT INTO "users" ("id","created_at","updated_at","deleted_at") VALUES ('1','2016-04-09T19:33:46-04:00','2016-04-09T19:33:46-04:00','<nil>')

(/home/nate/gocode/src/foo/main.go:35)
[2016-04-09 19:33:46]  [1.98ms]  UPDATE "users" SET "created_at" = '2016-04-09T19:33:46-04:00', "updated_at" = '2016-04-09T19:33:46-04:00', "deleted_at" = '<nil>'  WHERE "users".deleted_at IS NULL AND "users"."id" = '1'

(/home/nate/gocode/src/foo/main.go:35)
[2016-04-09 19:33:46]  [0.43ms]  INSERT INTO "cars" ("id","created_at","updated_at","deleted_at","owner_id") VALUES ('1','2016-04-09T19:33:46-04:00','2016-04-09T19:33:46-04:00','<nil>','1')

(/home/nate/gocode/src/foo/main.go:38)
[2016-04-09 19:33:46]  [0.64ms]  SELECT * FROM "cars"  WHERE "cars".deleted_at IS NULL

(/home/nate/gocode/src/foo/main.go:40)
[2016-04-09 19:33:46]  invalid association []
0

What is going on here? Is there some special tag that I have to use on the Owner field? I've tried using gorm:"ForeignKey:owner_id" and gorm:"AssociationForeignKey:owner_id", both giving the same result.

Simplest way in your case is specify foreign field name. So your

db.Model(cars[i]).Related(&cars[i].Owner)

should be like

db.Model(cars[i]).Related(&cars[i].Owner, "Owner")

Alternative ways are

  • Rename Owner and OwnerID fields to User and UserID or
  • Rename User structure to Owner

In these cases GORM will select right foreign keys automatically. From GORM documentation about associations:

If the field name is same as the variable's type name it could be omitted.