Gorm的Join操作没有映射到模型。

huangapple go评论87阅读模式
英文:

Gorm Joins not mapping to models

问题

我正在尝试通过使用SQL连接而不是Preload()来优化我的应用程序。
但是我遇到了一个问题,模型中的连接表始终为空。

我绝望地打开了一个新项目,并找到了一些简单的示例代码,但是问题依然存在。
如果你运行下面的代码,你会发现连接表始终是一个空数组。

我做错了什么吗?

import (
	"fmt"
	"log"

	"github.com/jinzhu/gorm"
	_ "github.com/lib/pq"
)

type Language struct {
	ID   uint   `gorm:"primary_key"`
	Name string
}

type Movie struct {
	ID         uint     `gorm:"primary_key"`
	Title      string
	Language   Language
	LanguageID uint
}

type Artist struct {
	ID     uint   `gorm:"primary_key"`
	Name   string
	Movies []Movie `gorm:"many2many:artist_movies"`
}

func createArtists() {
	langs := []Language{{Name: "english"},
		{Name: "tamil"},
		{Name: "french"}}

	for i, _ := range langs {
		if err := db.Create(&langs[i]).Error; err != nil {
			log.Fatal(err)
		}
	}

	movies := []Movie{
		{Title: "Nayagan", Language: langs[1]},
		{Title: "Anbe sivam", Language: langs[1]},
		{Title: "3 idiots", Language: langs[2]},
		{Title: "Shamithab", Language: langs[2]},
		{Title: "Dark Knight", Language: langs[0]},
		{Title: "310 to Yuma", Language: langs[0]},
	}
	for i, _ := range movies {
		if err := db.Create(&movies[i]).Error; err != nil {
			log.Fatal(err)
		}
	}

	artists := []Artist{
		{Name: "Madhavan", Movies: []Movie{movies[1], movies[2]}},
		{Name: "Kamal Hassan", Movies: []Movie{movies[0], movies[1]}},
		{Name: "Dhanush", Movies: []Movie{movies[3]}},
		{Name: "Aamir Khan", Movies: []Movie{movies[2]}},
		{Name: "Amitabh Bachchan", Movies: []Movie{movies[3]}},
		{Name: "Christian Bale", Movies: []Movie{movies[4], movies[5]}},
		{Name: "Russell Crowe", Movies: []Movie{movies[5]}},
	}

	for i, _ := range artists {
		if err := db.Create(&artists[i]).Error; err != nil {
			log.Fatal(err)
		}
	}
}

var db *gorm.DB

func main() {
	var err error
	db, err = gorm.Open("postgres", "user=admin password=1234 dbname=test sslmode=disable")
	if err != nil {
		log.Fatal(err)
	}
	db.AutoMigrate(new(Language), new(Movie), new(Artist))
	db.LogMode(true)

	createArtists()

	var artists []Artist

	if err = db.Joins("JOIN artist_movies on artist_movies.artist_id=artists.id").
		Joins("JOIN movies on movies.id=artist_movies.movie_id").
		Joins("JOIN languages on movies.language_id=languages.id").
		Where("languages.name=?", "tamil").
		Group("artists.id").Find(&artists).Error; err != nil {
		log.Fatal(err)
	}
	for _, ar := range artists {
		fmt.Println(ar.Movies)
	}

	artists = []Artist{}
	if err = db.Joins("JOIN artist_movies on artist_movies.artist_id=artists.id").
		Joins("JOIN movies on artist_movies.movie_id=movies.id").Where("movies.title=?", "Nayagan").
		Group("artists.id").Find(&artists).Error; err != nil {
		log.Fatal(err)
	}

	for _, ar := range artists {
		fmt.Println(ar.Movies)
	}

	artists = []Artist{}

	if err = db.Joins("JOIN artist_movies on artist_movies.artist_id=artists.id").
		Joins("JOIN movies on artist_movies.movie_id=movies.id").
		Where("movies.title in (?)", []string{"3 idiots", "Shamitabh", "310 to Yuma"}).
		Group("artists.id").Find(&artists).Error; err != nil {
		log.Fatal(err)
	}
	for _, ar := range artists {
		fmt.Println(ar.Movies)
	}
}
英文:

I'm trying to optimize my app by using sql joins instead of Preload().
But i've ran into an issue where the joined table in the model is always empty.

In desperation i've opened a new project and found some simple sample code, and again the same problem.
If you run the code below you'll see that the joined table is always an empty array.

Am i doing something wrong?

import (
"fmt"
"log"
"github.com/jinzhu/gorm"
_ "github.com/lib/pq"
)
type Language struct {
ID   uint `gorm:"primary_key"`
Name string
}
type Movie struct {
ID         uint `gorm:"primary_key"`
Title      string
Language   Language
LanguageID uint
}
type Artist struct {
ID     uint `gorm:"primary_key"`
Name   string
Movies []Movie `gorm:"many2many:artist_movies"`
}
func createArtists() {
langs := []Language{{Name: "english"},
{Name: "tamil"},
{Name: "french"}}
for i, _ := range langs {
if err := db.Create(&langs[i]).Error; err != nil {
log.Fatal(err)
}
}
movies := []Movie{
{Title: "Nayagan", Language: langs[1]},
{Title: "Anbe sivam", Language: langs[1]},
{Title: "3 idiots", Language: langs[2]},
{Title: "Shamithab", Language: langs[2]},
{Title: "Dark Knight", Language: langs[0]},
{Title: "310 to Yuma", Language: langs[0]},
}
for i, _ := range movies {
if err := db.Create(&movies[i]).Error; err != nil {
log.Fatal(err)
}
}
artists := []Artist{
{Name: "Madhavan", Movies: []Movie{movies[1],movies[2]}},
{Name: "Kamal Hassan", Movies: []Movie{movies[0], movies[1]}},
{Name: "Dhanush", Movies: []Movie{movies[3]}},
{Name: "Aamir Khan", Movies: []Movie{movies[2]}},
{Name: "Amitabh Bachchan", Movies: []Movie{movies[3]}},
{Name: "Christian Bale", Movies: []Movie{movies[4], movies[5]}},
{Name: "Russell Crowe", Movies: []Movie{movies[5]}},
}
for i, _ := range artists {
if err := db.Create(&artists[i]).Error; err != nil {
log.Fatal(err)
}
}
}
var db *gorm.DB
func main() {
var err error
db, err = gorm.Open("postgres", "user=admin password=1234 dbname=test sslmode=disable")
if err != nil {
log.Fatal(err)
}
db.AutoMigrate(new(Language), new(Movie), new(Artist))
db.LogMode(true)
createArtists()
var artists []Artist
if err = db.Joins("JOIN artist_movies on artist_movies.artist_id=artists.id").
Joins("JOIN movies on movies.id=artist_movies.movie_id").
Joins("JOIN languages on movies.language_id=languages.id").
Where("languages.name=?", "tamil").
Group("artists.id").Find(&artists).Error; err != nil {
log.Fatal(err)
}
for _, ar := range artists {
fmt.Println(ar.Movies)
}
artists = []Artist{}
if err = db.Joins("JOIN artist_movies on artist_movies.artist_id=artists.id").
Joins("JOIN movies on artist_movies.movie_id=movies.id").Where("movies.title=?", "Nayagan").
Group("artists.id").Find(&artists).Error; err != nil {
log.Fatal(err)
}
for _, ar := range artists {
fmt.Println(ar.Movies)
}
artists = []Artist{}
if err = db.Joins("JOIN artist_movies on artist_movies.artist_id=artists.id").
Joins("JOIN movies on artist_movies.movie_id=movies.id").
Where("movies.title in (?)", []string{"3 idiots", "Shamitabh", "310 to Yuma"}).
Group("artists.id").Find(&artists).Error; err != nil {
log.Fatal(err)
}
for _, ar := range artists {
fmt.Println(ar.Movies)
}

}

答案1

得分: 1

Gorm不会自动加载相关表中的数据。你需要在查询中使用Preload("table")来实现。在创建带有相关字段的记录时,可以使用关联。

文档:

Gorm目前不支持使用JOINS进行预加载,你需要使用SQL Builder创建SQL,并将结果的行映射到你的结构体中。

英文:

Gorm doesn't automatically load data into related tables. You have to use Preload("table") for that in your query. When creating records with related fields, use associations.

Docs

Gorm doesn't currently support preloading with JOINS, you have to create SQL with SQL Builder and map the resulting rows to your structures.

huangapple
  • 本文由 发表于 2016年11月21日 04:17:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/40708913.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定